WinSocket编程一般步骤-服务器端
第一步:包含WinSocket的头文件和动态链接库
#include <WinSock2.h> #pragma comment(lib, "ws2_32.lib")
第二步:初始化WSAStartup
WSADATA wsaData;
int nRes = WSAStartup(MAKEWORD(2,2), &wsaData);
if (0 != nRes)
{
std::cout<<"WSAStartup Failed!"<<std::endl;
WSACleanup();
return -1;
}
第三步:创建一个SOCKET,Create a SOCKET for listen for incoming connection requests
// Create a SOCKET for listen for incoming connection requests
SOCKET ListenSocket;
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == ListenSocket)
{
std::cout<<"socket Failed!"<<std::endl;
WSACleanup();
return -1;
}
第三步:绑定监听SOCKET(ListenSocket)与本地地址(Local Address)
SOCKADDR_IN ServAddr;
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = INADDR_ANY;
ServAddr.sin_port = htons(DEFAULT_PORT);
// bind
// The bind function associates a local address with a socket.
nRet = bind(ListenSocket, (SOCKADDR*)&ServAddr, sizeof(ServAddr));
if (0 != nRet)
{
std::cout<<"bind Failed!"<<std::endl;
WSACleanup();
closesocket(ListenSocket);
return -1;
}
第四步:监听listen
// listen
// Listen for incoming connection requests
// on the created socket
nRes = listen(ListenSocket, DEFAULT_MAX_LISTEN);
if (0 != nRes)
{
std::cout<<"listen Failed!"<<std::endl;
WSACleanup();
closesocket(ListenSocket);
return -1;
}
第五步:接受连接请求accept
// accept
// The accept function permits an incoming connection attempt on a socket.
int nLen = sizeof(ClientAddr);
AcceptSocket = accept(ListenSocket, (sockaddr*)&ClientAddr, &nLen);
if (INVALID_SOCKET == AcceptSocket)
{
std::cout<<"accept Failed!"<<std::endl;
WSACleanup();
closesocket(ListenSocket);
return -1;
}
第六步:接收客户端数据recv,如果accept成功,recv消息;如果accept不成功,则不recv消息
ZeroMemory(g_RecvBuf, DEFAULT_BUFLEN);
nByteLen = recv(AcceptSocket, g_RecvBuf, DEFAULT_BUFLEN+1, 0);
if ((0 == strcmp(g_RecvBuf, "quit")) || (0 == strcmp(g_RecvBuf, "QUIT")))
{
std::cout<<"Client QUIT!"<<std::endl;
WSACleanup();
closesocket(ListenSocket);
closesocket(AcceptSocket);
return 0;
}
if (0 == nByteLen)
{
std::cout<<"Client QUIT!"<<std::endl;
WSACleanup();
closesocket(ListenSocket);
closesocket(AcceptSocket);
return 0;
}
if (SOCKET_ERROR == nByteLen)
{
std::cout<<"recv Failed!"<<std::endl;
WSACleanup();
closesocket(ListenSocket);
closesocket(AcceptSocket);
return -1;
}
std::cout<<"Client : "<<g_RecvBuf<<std::endl;
第七步(可选):Send消息至客户端
// send data to the client
// The send function sends data on a connected socket.
ZeroMemory(g_SendBuf, DEFAULT_BUFLEN);
std::cout<<"> ";
gets(g_SendBuf);
if ((0 == strcmp(g_SendBuf, "quit")) || (0 == strcmp(g_SendBuf, "QUIT")))
{
std::cout<<"Server QUIT!"<<std::endl;
WSACleanup();
closesocket(ListenSocket);
closesocket(AcceptSocket);
return 0;
}
nByteLen = send(AcceptSocket, g_SendBuf, strlen(g_SendBuf)+ 1, 0);
if (SOCKET_ERROR == nByteLen)
{
std::cout<<"send Failed!"<<std::endl;
WSACleanup();
closesocket(AcceptSocket);
closesocket(ListenSocket);
return -1;
}
std::cout<<"Server : "<<g_SendBuf<<std::endl;
如果需要连续不断地和客户端进行交互的话,则可以将send和recv两个步骤绑定在一起,放在一个while(true)循环中,直到服务器或者客户端某一方退出。
代码实例如下:
while (true) { // receive the data from client ZeroMemory(g_RecvBuf, DEFAULT_BUFLEN); nByteLen = recv(AcceptSocket, g_RecvBuf, DEFAULT_BUFLEN+1, 0); if ((0 == strcmp(g_RecvBuf, "quit")) || (0 == strcmp(g_RecvBuf, "QUIT"))) { std::cout<<"Client QUIT!"<<std::endl; WSACleanup(); closesocket(ListenSocket); closesocket(AcceptSocket); return 0; } if (0 == nByteLen) { std::cout<<"Client QUIT!"<<std::endl; WSACleanup(); closesocket(ListenSocket); closesocket(AcceptSocket); return 0; } if (SOCKET_ERROR == nByteLen) { std::cout<<"recv Failed!"<<std::endl; WSACleanup(); closesocket(ListenSocket); closesocket(AcceptSocket); return -1; } std::cout<<"Client : "<<g_RecvBuf<<std::endl; // send data to the client // The send function sends data on a connected socket. ZeroMemory(g_SendBuf, DEFAULT_BUFLEN); std::cout<<"> "; gets(g_SendBuf); if ((0 == strcmp(g_SendBuf, "quit")) || (0 == strcmp(g_SendBuf, "QUIT"))) { std::cout<<"Server QUIT!"<<std::endl; WSACleanup(); closesocket(ListenSocket); closesocket(AcceptSocket); return 0; } nByteLen = send(AcceptSocket, g_SendBuf, strlen(g_SendBuf)+ 1, 0); if (SOCKET_ERROR == nByteLen) { std::cout<<"send Failed!"<<std::endl; WSACleanup(); closesocket(AcceptSocket); closesocket(ListenSocket); return -1; } std::cout<<"Server : "<<g_SendBuf<<std::endl; }
第八步:清理已生成的SOCKET并退出。
WSACleanup(); closesocket(ListenSocket); closesocket(AcceptSocket); return 0;
由于前面的所有步骤中,都对异常以及正常退出的情况作出了处理,因此最后清理这个步骤其实也是可选的。