学习:WinSock TCP 长连接(while循环)

前面的程序,不管服务器端还是客户端,都有一个问题,就是处理完一个请求立即退出了,没有太大的实际意义。能不能像Web服务器那样一直接受客户端的请求呢?能,使用 while 循环即可。

这里唯一需要注意的是,每次 客户端 进行连接完之后,都需要进行socketclose()的操作,原因是 服务端 调用 closesocket() 不仅会关闭服务器端的 socket,还会通知客户端连接已断开,所以客户端也需要直接进行socketclose()的操作

服务端的代码:

#include<winSock2.h>
#include<iostream>
#pragma comment(lib, "ws2_32.lib") //添加动态链接库

using namespace std;

int main(int argc, char * argv[]) {
	const int	BUFSIZE = 1024;
	SOCKET		ListeningSocket; //定义一个套接字变量
	SOCKET		NewConnection; //客户端的请求生成的新的套接字
	SOCKADDR_IN ClientAddr;
	SOCKADDR_IN ServerAddr;
	char		Message[BUFSIZE];
	int			ClientAddrLen;
	ZeroMemory(Message, BUFSIZE);

	if (argc <= 1)
	{
		cout << "USAGE: TcpServer <Listen Port>" << endl;
		return -1;
	}


	int ret; //用来检查初始化成功是否
	WSADATA wsaDATA; // 创建一个WSADATA 用来初始化套接字网络库

	if ((ret = WSAStartup(MAKEWORD(2, 2), &wsaDATA)) != 0) { // 初始化套接字网络库WinSock2.2版本
		cout << "WSAStartup初始化失败 with error " << ret << endl;
		return -1;
	}

	//创建套接字 AF_INET协议 SOCK_STREAM流 TCP协议
	if ((ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) {
		cout << "创建套接字失败 with error " << WSAGetLastError() << endl;
		WSACleanup();
		return -1;
	}

	//绑定套接字
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(atoi(argv[1]));
	ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	if (bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
		cout << "绑定套接字失败 with error " << WSAGetLastError() << endl;
		closesocket(ListeningSocket);
		WSACleanup();
		return -1;
	}

	//监听套接字
	if ((ret = listen(ListeningSocket, 1)) == SOCKET_ERROR) {
		cout << "监听套接字失败 with error " << WSAGetLastError() << endl;
		closesocket(ListeningSocket);
		WSACleanup();
		return -1;
	}
	cout << "正在监听端口" << argv[1] << "中..." << endl;


	//接收客户端数据
	ClientAddrLen = sizeof(SOCKADDR);
	while (true) {
		if ((NewConnection = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &ClientAddrLen)) == INVALID_SOCKET) {//创建一个当前客户端和服务端的套接字,accept会阻塞,后面的不能继续执行,直到有新的请求
			cout << "创建NewConnection失败 with error " << WSAGetLastError() << endl;
			closesocket(ListeningSocket);
			WSACleanup();
			return -1;
		}

		int StrLen = recv(NewConnection, Message, sizeof(Message), 0);
		cout << "客户端 > " << Message << endl;

		send(NewConnection, Message, StrLen, 0);
		closesocket(NewConnection);

		ZeroMemory(Message, BUFSIZE);
	}

	//关闭套接字
	closesocket(ListeningSocket);
	WSACleanup();


	return 0;
}

客户端的代码:

#include<WinSock2.h>
#include<iostream>
#pragma comment(lib, "ws2_32.lib") //添加动态链接库
#pragma warning(disable:4996) //忽略旧函数使用缺陷的警告

using namespace std;

int main(int argc, char * argv[]) {
	const int	BUFSIZE = 1024;
	SOCKET		ClientSocket;
	SOCKADDR_IN ServerAddr;
	char		SendBuf[BUFSIZE];  //发送存储的数据缓冲区
	char		BufRecv[BUFSIZE]; //接收收到的数据缓冲区

	ZeroMemory(SendBuf, BUFSIZE);
	ZeroMemory(BufRecv, BUFSIZE);
	strcpy(SendBuf, "Hello, My Name is Client");

	if (argc <= 2)
	{
		cout << "USAGE: TcpServer <Server IP> <Server PORT>" << endl;
		return -1;
	}

	WSADATA		WSAData;
	int			ret;
	if ((ret = WSAStartup(MAKEWORD(2, 2), &WSAData)) != 0) {
		cout << "WSAStartup初始化失败 with error " << ret << endl;
		return -1;
	}


	//cout << "连接建立成功!" << endl;;

	while (true) {
		//创建套接字
		if ((ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) {
			cout << "创建套接字失败 with error " << WSAGetLastError() << endl;
			WSACleanup();
			return -1;
		}

		//连接connet服务端
		ServerAddr.sin_family = AF_INET;
		ServerAddr.sin_addr.s_addr = inet_addr(argv[1]);
		ServerAddr.sin_port = htons(atoi(argv[2]));
		if (connect(ClientSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR) {
			cout << "连接服务端失败 with error " << WSAGetLastError() << endl;
			closesocket(ClientSocket);
			WSACleanup();
			return -1;
		}

		cout << "客户端 > ";
		cin >> SendBuf;

		//send发送数据
		if ((ret = send(ClientSocket, SendBuf, strlen(SendBuf), 0)) == SOCKET_ERROR) {
			cout << "send failed with error " << WSAGetLastError() << endl;;
			closesocket(ClientSocket);
			WSACleanup();
			return -1;
		}

		recv(ClientSocket, BufRecv, BUFSIZ, 0);
		cout << "服务端 > " << BufRecv << endl;

		ZeroMemory(SendBuf, BUFSIZE);
		ZeroMemory(BufRecv, BUFSIZE);

		//关闭套接字
		closesocket(ClientSocket);
	}

	WSACleanup();
	return 0;


}
posted @ 2020-01-09 22:56  zpchcbd  阅读(578)  评论(0编辑  收藏  举报