winSockets编程阻塞模式(服务端)
Posted YuRi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了winSockets编程阻塞模式(服务端)相关的知识,希望对你有一定的参考价值。
在阻塞模式下,在I/O操作完成前,执行的操作函数将一直等候而不会立即返回,该函数所在的线程会阻塞在这里。相反,在非阻塞模式下,套接字函数立即返回,而不管I/O是否完成。
#生产者和消费者模式
##
服务器端的简化形式(#这套流程需要完全背诵#)
/*****************初始化***********************/ int retVal; WSAData wsd; retVal = WSAStartup(MAKEWORD(1, 1), &wsd); /****************************************/ //创建套接字 sSever = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /************绑定套接字****************************/ SOCKADDR_IN addrServ; addrServ.sin_family = AF_INET; addrServ.sin_port = htons(5999); addrServ.sin_addr.s_addr = INADDR_ANY; retVal = bind(sSever, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN)); /****************************************/ //监听 retVal = listen(sSever, 1); /***************获取客户端请求,线程在阻塞************************/ SOCKADDR_IN addrClient; int addrClientlen = sizeof(addrClient); sClient = accept(sSever, (sockaddr FAR*)&addrClient, &addrClientlen); /***************************************/ while (true) //从接收缓冲区中读取数据,每次一个字节; { nReadLen = recv(s, buf + nDataLen, 1, 0);
........ } retVal = send(s, str, strlen(str), 0); //发送数据(一次发送)
#完整代码#
#include <iostream> #include <WINSOCK2.H> #pragma comment(lib, "wsock32.lib") #define SERVER_EXIT_OK 0 //服务器正常退出; #define SERVER_DLL_REEOR 1 //调用Windows sockets DLL失败; #define SERVER_API_ERROR 2 //调用Windows sockets API失败; #define SERVERPORT 5555 //服务器TCP端口; char bufRecv[MAX_PATH]; //读缓冲区; char bufSend[MAX_PATH]; //写缓冲区; SOCKET sServer; //服务器监听套接字; SOCKET sClient; //接受客户端套接字; BOOL bConning; //与客户端的连接状态; void InitMember(void); //初始化成员变量; int ExitClient(int nExit); //客户端退出; BOOL RecvLine(SOCKET s, char* buf); //读取一行数据; BOOL SendLine(SOCKET s, char* buf); //发送一行数据; int HandleSocketError(char *str); //对Windows sockets API调用错误处理; void ShowSocketMsg(char* str); //显示错误信息; int main(int argc, char* argv[]) { InitMember(); WSADATA wsaData; //Windows sockets DLL版本信息 int retVal; //调用Windows sockets API返回值 retVal = WSAStartup(MAKEWORD(1, 1), &wsaData); if (0 != retVal) { ShowSocketMsg("找不到可用的Socket DLL!"); return SERVER_DLL_REEOR; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { ShowSocketMsg("Can not find a usable Windows Sockets dll!"); WSACleanup(); return SERVER_DLL_REEOR; } //创建套接字; /*******************************************************/ sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == sServer) { return HandleSocketError("Failed socket()!"); } /********************************************************/ //服务器套接字地址; SOCKADDR_IN addrServ; addrServ.sin_family = AF_INET; addrServ.sin_port = htons(SERVERPORT); addrServ.sin_addr.s_addr = INADDR_ANY; retVal = bind(sServer, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));//绑定套接字; if (SOCKET_ERROR == retVal) { closesocket(sServer); return HandleSocketError("Failed bind()!"); } retVal = listen(sServer, 1);//开始监听; if (SOCKET_ERROR == retVal) { closesocket(sServer); return HandleSocketError("Failed listen()!"); } std::cout << "Server succeeded!" <<std::endl;//等待客户端的连接; std::cout << "Waiting for new clients..." <<std::endl; /***********接受客户端请求****************************/ sockaddr_in addrClient; int addrClientlen = sizeof(addrClient); sClient = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientlen); if (INVALID_SOCKET == sClient) { closesocket(sServer); return HandleSocketError("Failed accept()!"); } else { bConning = TRUE;//客户端请求成功; } //显示客户端的IP和端口; char *pClientIP = inet_ntoa(addrClient.sin_addr); u_short clientPort = ntohs(addrClient.sin_port); std::cout << "Accept a client." <<std::endl; std::cout << "IP: " << pClientIP <<std::endl; std::cout << "Port: " << clientPort <<std::endl; if (!RecvLine(sClient, bufRecv))//接收客户端数据; { return ExitClient(SERVER_API_ERROR); } std::cout << bufRecv <<std::endl;//显示客户端数据; strcpy_s(bufSend, "Hello,Client!\n");//向客户端发送数据; if (!SendLine(sClient, bufSend)) { return ExitClient(SERVER_API_ERROR); } std::cout << "Server exiting..." <<std::endl;//显示退出信息; return ExitClient(SERVER_EXIT_OK); } void InitMember(void) { memset(bufRecv, 0, MAX_PATH); memset(bufSend, 0, MAX_PATH); sServer = INVALID_SOCKET; sClient = INVALID_SOCKET; bConning = FALSE; } int ExitClient(int nExit) { closesocket(sServer); closesocket(sClient); WSACleanup(); return nExit; } BOOL RecvLine(SOCKET s, char* buf) { BOOL retVal = TRUE; //返回值 BOOL bLineEnd = FALSE; //行结束 int nReadLen = 0; //读入字节数 int nDataLen = 0; //数据长度 while (!bLineEnd && bConning) //与客户端连接 没有换行 { nReadLen = recv(s, buf + nDataLen, 1, 0);//每次接收一个字节 //错误处理 if (SOCKET_ERROR == nReadLen) { int nErrCode = WSAGetLastError();//错误代码 if (WSAENOTCONN == nErrCode) { ShowSocketMsg("The socket is not connected!"); } else if (WSAESHUTDOWN == nErrCode) { ShowSocketMsg("The socket has been shut down!"); } else if (WSAETIMEDOUT == nErrCode) { ShowSocketMsg("The connection has been dropped!"); } else if (WSAECONNRESET == nErrCode) { ShowSocketMsg("The virtual circuit was reset by the remote side!"); } else { } retVal = FALSE; //读数据失败 break; //跳出循环 } if (0 == nReadLen)//客户端关闭 { retVal = FALSE; //读数据失败 break; //跳出循环 } //读入数据 if (‘\n‘ == *(buf + nDataLen)) //换行符 { bLineEnd = TRUE; //接收数据结束 } else { nDataLen += nReadLen; //增加数据长度 } } return retVal; } BOOL SendLine(SOCKET s, char* str) { int retVal;//返回值 retVal = send(s, str, strlen(str), 0);//一次发送 //错误处理 if (SOCKET_ERROR == retVal) { int nErrCode = WSAGetLastError();//错误代码 if (WSAENOTCONN == nErrCode) { ShowSocketMsg("The socket is not connected!"); } else if (WSAESHUTDOWN == nErrCode) { ShowSocketMsg("The socket has been shut down!"); } else if (WSAETIMEDOUT == nErrCode) { ShowSocketMsg("The connection has been dropped!"); } else { } return FALSE; //发送失败 } return TRUE; //发送成功 } int HandleSocketError(char *str) { ShowSocketMsg(str); //显示错误消息 WSACleanup(); //卸载Windows socket DLL return SERVER_API_ERROR;//退出应用程序 } void ShowSocketMsg(char* str) { MessageBox(NULL, str, "SERVER ERROR", MB_OK); }
以上是关于winSockets编程阻塞模式(服务端)的主要内容,如果未能解决你的问题,请参考以下文章