回射程序2(服务器)——服务器接收定长数据

来源:互联网 发布:江西服装学院知乎 编辑:程序博客网 时间:2024/04/28 00:38

这是我编写的第二个回射程序。程序大体是这样的:


客户端的编写上一篇给出的客户端的编写方法是一样的,同样用recvline方法接收一行数据。这里不再赘述。

在服务器的编写上,这里不再像前面使用常规的recv方法接收数据,而是自己定义一个函数recvn,用于接收固定长度的数据,其中固定长度由运行程序指定。

这里实现的内容很简单,在客户端创建一个unsigned int类型的变量,发送到服务器端,服务器端使用recvn接收长度为sizeof(unsigned int)的数据,作为接收固定长度数据的体现。

PS:值得注意的是,在发送unsigned int类型的数据时,需要进行字节序的转换。htonl、ntohl等等一定要搞明白!!!

下面贴代码:

// 回显服务器2.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <stdio.h>#include <stdlib.h>#include <winsock2.h>#include <string.h>#pragma comment(lib,"wsock32.lib")#define  SERVERPROT 6000#define  MAXSIZE 100//函数声明int recvn(SOCKET s, char * recvbuf, unsigned int fixedlen);BOOL recvline(SOCKET S,char* buf);int _tmain(int argc, _TCHAR* argv[]){//初始化WinSockWSADATA wsaData;int ret = WSAStartup(MAKEWORD(2,2),&wsaData);if(ret!=0){printf("WSAStartup() failed!code:%d\n",WSAGetLastError());return -1;}if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2){WSACleanup();printf("Invalid WinSock Version\n");return -1;}//创建监听套接字SOCKET slisten;slisten = socket(AF_INET,SOCK_STREAM,0);if(slisten == INVALID_SOCKET){printf("socket() failed!code:%d\n",WSAGetLastError());WSACleanup();return -1;}//构建服务器本地地址信息struct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(SERVERPROT);serveraddr.sin_addr.S_un.S_addr =  INADDR_ANY;//绑定ret = bind(slisten,(sockaddr*)&serveraddr,sizeof(serveraddr));if(ret == SOCKET_ERROR){printf("bind() failed!code:%d\n",WSAGetLastError());closesocket(slisten);WSACleanup();return -1;}//侦听连接请求ret = listen(slisten,5);if(ret == SOCKET_ERROR){printf("listen() failed!code:%d\n",WSAGetLastError());closesocket(slisten);WSACleanup();return -1;}printf("waiting for client connecting...\n");//接收客户端连接struct sockaddr_in clientaddr;int clientaddrlen = sizeof(clientaddr);SOCKET sServer;//连接套接字unsigned int recvdata; //用于接收发送过来的数字char sendbuf[MAXSIZE];//发送缓存sServer = accept(slisten,(struct sockaddr*)&clientaddr,&clientaddrlen);if(sServer == INVALID_SOCKET){printf("accept() failed!code:%d\n",WSAGetLastError());closesocket(slisten);WSACleanup();return -1;}//memset(buff,0,MAXSIZE);memset(sendbuf,0,MAXSIZE);while(TRUE)  //循环接收数据{ret = recvn(sServer,(char*)&recvdata,sizeof(unsigned int));if(ret==SOCKET_ERROR){int nErrCode = WSAGetLastError();//错误代码if (WSAENOTCONN == nErrCode){printf("The socket is not connected!\n");}else if(WSAESHUTDOWN == nErrCode){printf("The socket has been shut down!\n");}else if (WSAETIMEDOUT == nErrCode){printf("The connection has been dropped!\n");}else if (WSAECONNRESET == nErrCode){printf("The virtual circuit was reset by the remote side!\n");}else{}closesocket(sServer);closesocket(slisten);WSACleanup();return -1;}recvdata = ntohl(recvdata);sprintf(sendbuf,"echo:%d\n",recvdata);printf("%s\n",sendbuf);ret = send(sServer,sendbuf,strlen(sendbuf),0);if (SOCKET_ERROR == ret){int nErrCode = WSAGetLastError();//错误代码if (WSAENOTCONN == nErrCode){printf("The socket is not connected!\n");}else if(WSAESHUTDOWN == nErrCode){printf("The socket has been shut down!\n");}else if (WSAETIMEDOUT == nErrCode){printf("The connection has been dropped!\n");}else{}closesocket(sServer);closesocket(slisten);WSACleanup();return -1;}}closesocket(sServer);closesocket(slisten);WSACleanup();return 0;}//指定长度接收int recvn(SOCKET s, char * recvbuf, unsigned int fixedlen){int iResult;    //存储单次recv操作的返回值int cnt;         //用于统计相对于固定长度,剩余多少字节尚未接收cnt = fixedlen;while ( cnt > 0 ) {iResult = recv(s, recvbuf, cnt, 0);if ( iResult < 0 ){//数据接收出现错误,返回失败printf("接收发生错误: %d\n", WSAGetLastError());return -1;}if ( iResult == 0 ){//对方关闭连接,返回已接收到的小于fixedlen的字节数printf("连接关闭\n");return fixedlen - cnt;}//printf("接收到的字节数: %d\n", iResult);//接收缓存指针向后移动recvbuf +=iResult;//更新cnt值cnt -=iResult;         }return fixedlen;}


0 0
原创粉丝点击