[Win32] Windows Sockets 2笔记(3)TCP Server端的实现(长数据接收+超时机制)
来源:互联网 发布:腾讯大数据 会 11.22 编辑:程序博客网 时间:2024/05/18 22:17
本博文由CSDN博主zuishikonghuan所作,版权归zuishikonghuan所有,转载请注明出处:http://blog.csdn.net/zuishikonghuan/article/details/48027823
在上一篇中,我说了Winsock2的基本函数,这一篇,我们来制作一个TCP Server端,并且要求这个TCP Server端要支持长数据接收和接收超时机制
由于函数已经讲过了,所以socket函数不再重复,请见上一篇:[Win32] Windows Sockets 2笔记(2)基本函数。地址:http://blog.csdn.net/zuishikonghuan/article/details/48001135
超时机制比较容易,就是select函数,详细见上一篇
要想实现长数据接收,因为双方无法得知对方要发送多长的数据,同时,发送和接收都是协议完成的,socket只是进行了简单的缓冲区复制,因此无论是recv一次,还是循环recv直到出错,都是不可取的。
有两种解决方法:
方法1。指定一个结束符,一直接收到出现结束符为止,这就要求正文中不能有这个结束符,如果有必须替换或者编码
方法2。指定一个应用层协议,或自己设计一个应用层协议,能让对方预先知道你要发多长的包,比如HTTP就在协议头里有一个Content-length字段,可以让对方知道数据包有多长。
在本例中,我将采用方法2,并预定一个协议,从数据包开头计算,直到出现第一个“@”字符,这个字符之前的数据是数据长度。
源代码如下:
#include <winsock2.h>#pragma comment(lib , "Ws2_32.lib")#include <Windows.h>//等待接收操作//参数1:套接字描述符 参数2:等待的秒数BOOL WaitRecv(SOCKET s,int timeout){fd_set nfds;RtlZeroMemory(&nfds, sizeof(fd_set));nfds.fd_array[0] = s;nfds.fd_count = 1;timeval time = { timeout, 0 };if (select(0, &nfds, NULL, NULL, &time) <= 0){return FALSE;}return TRUE;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){WORD wVersionRequested;WSADATA wsaData;wVersionRequested = MAKEWORD(2, 2);SOCKET Socket, connectsock;sockaddr_in addr, clientaddr;if (WSAStartup(wVersionRequested, &wsaData) != 0){MessageBox(NULL, TEXT("Winsock开启失败"), TEXT("错误"), MB_ICONERROR);return 1;}Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (Socket == INVALID_SOCKET){MessageBox(NULL, TEXT("Socket创建失败"), TEXT("错误"), MB_ICONERROR);return 1;}addr.sin_family = AF_INET;addr.sin_port = htons(8888);addr.sin_addr.S_un.S_addr = INADDR_ANY;//inet_addr("127.0.0.1");if (bind(Socket, (sockaddr*)&addr, sizeof(sockaddr_in)) == SOCKET_ERROR){MessageBox(NULL, TEXT("Socket绑定到本机地址失败"), TEXT("错误"), MB_ICONERROR);exit(1);}if (listen(Socket, SOMAXCONN) == SOCKET_ERROR){MessageBox(NULL, TEXT("Socket监听失败"), TEXT("错误"), MB_ICONERROR);exit(1);}char msg[1001];int readlen = 0;int addrlen = sizeof(sockaddr_in);char* ip=NULL;while (1){connectsock = accept(Socket, (sockaddr*)&clientaddr, &addrlen);if (connectsock == INVALID_SOCKET)continue;RtlZeroMemory(msg, 1001);ip=inet_ntoa(clientaddr.sin_addr);//对方IP地址if (!WaitRecv(connectsock, 2)){//等待接收closesocket(connectsock);continue;//超时,关闭套接字并继续接收}int r = recv(connectsock, msg, 1000, 0);int len = 0;if (r > 0){unsigned int x = (unsigned int)strstr(msg, "@");//找到第一个出现@的位置,按照预先的协议,@之前是完整的数据长度if (x != 0){msg[x - (unsigned int)msg] = '\0';//将@换成字符串结束符len = atoi(msg);//获取长度msg[x - (unsigned int)msg] = '@';//替换回来readlen = r;//已经读取的字节MessageBoxA(NULL, msg, "收到数据", 0);while (readlen < len){//一直接收,直到达到我们认为的长度RtlZeroMemory(msg, 1001);if (!WaitRecv(connectsock, 2))break;//超时r = recv(connectsock, msg, 1000, 0);if (r <= 0)break;readlen += r;MessageBoxA(NULL, msg, "收到数据", 0);}}else{closesocket(connectsock);}}MessageBoxA(NULL, "数据接收完成", ip, 0);send(connectsock, msg, strlen(msg), 0);closesocket(connectsock);}return 0;}
0 0
- [Win32] Windows Sockets 2笔记(3)TCP Server端的实现(长数据接收+超时机制)
- [Win32] Windows Sockets 2笔记(4)TCP Client端的实现(长数据接收+超时机制)
- [Win32] Windows Sockets 2笔记(2)基本函数
- [Win32] Windows Sockets 2笔记(1)在开始之前
- UDP和TCP通信机制(实现简单的数据发送与接收)
- Windows Sockets网络编程(2)TCP select & thread
- Windows Sockets网络编程(2)TCP Stream拆分、拼接
- TCP(SOCKETS)编程 C/C++实现
- TCP(SOCKETS)编程 C/C++实现
- linux 内核tcp接收数据的实现
- linux 内核tcp接收数据的实现
- Windows Sockets网络编程(0)TCP In Action
- Windows Sockets网络编程(1)TCP select & thread
- Windows Sockets网络编程(0)TCP In Action
- 使用setsockopt()接口,设置TCP的接收与发送超时,Invalid argument错误问题
- 使用setsockopt()接口,设置TCP的接收与发送超时,Invalid argument错误问题
- 使用setsockopt()接口,设置TCP的接收与发送超时,Invalid argument错误问题
- php中利用http的长链接实现接收数据
- 二叉树的遍历
- 线性表(3)--习题
- HDU 1385 Minimum Transport Cost(folyd+记录路径)
- 同学会
- [Java Web]ibatis使用queryForMap实现数据查找等操作
- [Win32] Windows Sockets 2笔记(3)TCP Server端的实现(长数据接收+超时机制)
- Android存储使用参考
- Maven错误信息:Missing artifact jdk.tools:jdk.tools:jar:1.6
- 界面编辑神器--Bootstrap
- java 用 jackson 进行 xml bean 互转
- Android使用XML Shape绘制带阴影效果的圆形按钮
- 学习的第一个FFmpeg-demo---解封装且解码视频后存储为yuv和h.264文件
- linux常用命令(5):rm命令
- 随机组队_第一场