WinSock编程(TCP)

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;

由于前面的所有步骤中,都对异常以及正常退出的情况作出了处理,因此最后清理这个步骤其实也是可选的。

原文地址:https://www.cnblogs.com/Jasonscor/p/3309414.html