介绍
默认情况下,建立的套接字都是阻塞的,程序会停在等待网络事件的地方(accept),直到网络io条件满足,才会继续向下执行
代码实现
#include <WinSock2.h>#include <Windows.h>#include <WS2tcpip.h>#include <stdlib.h>#include <stdio.h>#pragma comment(lib,"ws2_32.lib")#define DEFAULT_BUFLEN 512#define DEFAULT_PORT 27015int __cdecl main(int argc,TCHAR* argv[]) {WSADATA wsaData;int iResult;SOCKET ServerSocket = INVALID_SOCKET;SOCKET AcceptSocket = INVALID_SOCKET;char recvbuf[DEFAULT_BUFLEN];int recvBufLen = DEFAULT_BUFLEN;sockaddr_in addrClient;int addrClinetLen = sizeof(sockaddr_in);iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult!=0){printf_s("wsatartup faild with error code %d\n", iResult);return 1;}ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);if (ServerSocket==INVALID_SOCKET){printf_s("SOCKET FAILED WITH ERROR CODE %d",WSAGetLastError());WSACleanup();return 1;}SOCKADDR_IN addrServ;addrServ.sin_family = AF_INET;addrServ.sin_port = htons(DEFAULT_PORT);addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);iResult = bind(ServerSocket,(const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN));if (iResult==SOCKET_ERROR){printf_s("bind falied with error code %d\n",iResult);closesocket(ServerSocket);WSACleanup();return 1;}iResult = listen(ServerSocket,SOMAXCONN);if (iResult==SOCKET_ERROR){printf_s("listen failed with error code %d",iResult);closesocket(ServerSocket);WSACleanup();return -1;}printf_s("TCP server starting");int err;while (true){AcceptSocket = accept(ServerSocket, (sockaddr FAR*) & addrClient, &addrClinetLen);if (AcceptSocket == INVALID_SOCKET){printf_s("accetp failed \n");closesocket(ServerSocket);WSACleanup();return 1;}while (true){memset(recvbuf, 0, recvBufLen);iResult = recv(AcceptSocket, recvbuf, recvBufLen, 0);if (iResult>0){printf_s("recv data %d byte\n",iResult);int iSendResult = send(AcceptSocket, recvbuf, iResult, 0);if (iSendResult == SOCKET_ERROR) {printf("send failed with error: %d\n", WSAGetLastError());closesocket(AcceptSocket);WSACleanup();return 1;}printf("Bytes sent: %d\n", iSendResult);continue;}else if (iResult == 0){printf_s("conn closeing ....\n");closesocket(AcceptSocket);break;}else{printf_s("%d",iResult);printf_s("recv failed with error%d\n",WSAGetLastError());closesocket(AcceptSocket);closesocket(ServerSocket);WSACleanup();return 1;}}}closesocket(ServerSocket);closesocket(AcceptSocket);WSACleanup();return 0;}
评价
- 优点:使用非常简单直接
- 缺点:
- 无法同时处理多个套接字
- 程序会在等待io处卡死,程序效率低下
改进思路:
- 多线程并发处理多个io,即一个线程处理一个socket,
- 问题:线程频繁创建,唤醒,睡眠。导致用户态内核态频繁切换。增大系统开销
- 线程同步,条件竞争,需要研究锁问题
- 异步,非阻塞处理多个io
- 这种情况下,程序仍然为单线程,但是对io处理上使用回调机制,捕获io条件满足时机达到一对多效果
- 问题:确定网络事件发生、网络io消息,回调机制
