基于Socket的MFC网络编程

一、基于TCP协议的编程步骤

服务器端:

1. 加载套接字库(WSAStartup)

2. 创建用于监听的套接字(socket),然后将其绑定到本地SOCKADDR(bind),并将其设为监听模式(listen)

3. 等待客户请求的到来:一旦收到客户连接请求,返回一个对应该连接的套接字(accept)

4. 利用返回的套接字与客户端进行通信(recv/send)

5. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)

	// 加载套接字库
	WSAData wsaData;
	if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
	{
		return;
	}
	if(1 != LOBYTE(wsaData.wVersion) ||
	   1 != HIBYTE(wsaData.wVersion))
	{
		// 终止对套接字库的使用
		WSACleanup();
		return;
	}

	// 创建用于监听的套接字
	SOCKET sockListen = socket(AF_INET, SOCK_STREAM, 0);

	// 绑定监听套接字到某个本地地址信息结构体
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrSrv.sin_port = htons(6000);
	bind(sockListen, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

	// 将监听套接字设为监听模式,准备接收客户请求
	listen(sockListen, 6);

	// 处理客户请求
	SOCKADDR_IN addrClient;
	int len = sizeof(SOCKADDR);
	while(1)
	{
		// 等待客户请求的到来
		// 每次接收到客户请求后,返回对应本次连接的套接字
		// 建立连接后,就可以使用返回的套接字与客户端进行通信了
		SOCKET sockSrv = accept(sockListen, (SOCKADDR *)&addrClient, &len);
		
		// 发送数据
		char sendBuf[100];
		sprintf(sendBuf, "Welcome %s to http://www.communication.org", inet_ntoa(addrClient.sin_addr));
		send(sockSrv, sendBuf, strlen(sendBuf) + 1, 0);

		// 接收数据
		char recvBuf[100];
		recv(sockSrv, recvBuf, sizeof(recvBuf), 0);
		printf("%s\n", recvBuf);

		// 关闭本次连接的套接字
		closesocket(sockSrv);
	}

	// 终止对套接字库的使用
	WSACleanup();

客户端:

1. 加载套接字库(WSAStartup)

2. 创建用于通信的套接字(socket)

3. 向服务器发出连接请求(connect)

4. 利用已连接的套接字与服务器进行通信(send/recv)

5. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)

	// 加载套接字库
	WSADATA wsaData;
	if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
	{
		return;
	}
	if (1 != LOBYTE(wsaData.wVersion) ||
		1 != HIBYTE(wsaData.wVersion))
	{
		// 终止对套接字库的使用
		WSACleanup();
		return;
	}

	// 创建套接字
	SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);

	// 向服务器发出连接请求
	// 建立连接后,就可以利用请求套接字与服务器进行通信了
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addrSrv.sin_port = htons(6000);
	connect(sockClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

	// 接收数据
	char recvBuf[100];
	recv(sockClient, recvBuf, sizeof(recvBuf), 0);
	printf("%s\n", recvBuf);

	// 发送数据
	send(sockClient, "This is TcpClient One.", strlen("This is TcpClient One.")+1, 0);

	// 关闭套接字,终止套接字库使用
	closesocket(sockClient);
	WSACleanup();

二、基于UDP协议的编程步骤

服务器端:

1. 加载套接字库(WSAStartup)

2. 创建用于通信的套接字(socket),然后将其绑定到本地SOCKADDR(bind)

3. 利用创建的套接字与客户端进行通信(recvfrom/sendto)

4. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)

	// 加载套接字库
	WSAData wsaData;
	if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
	{
		return;
	}
	if(1 != LOBYTE(wsaData.wVersion) ||
	   1 != HIBYTE(wsaData.wVersion))
	{
		// 终止对套接字库的使用
		WSACleanup();
		return;
	}


	// 创建套接字
	SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);

	// 绑定套接字到某个本地地址信息结构体
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrSrv.sin_port = htons(6000);
	bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

	// 等待并接收数据
	// 直接利用绑定到本地的套接字进行数据接收
	SOCKADDR_IN addrClient;
	int len = sizeof(SOCKADDR);
	char recvBuf[100];
	recvfrom(sockSrv, recvBuf, sizeof(recvBuf), 0,
		(SOCKADDR *)&addrClient, &len);
	printf("%s\n", recvBuf);

	// 关闭套接字,并终止套接字库的使用
	closesocket(sockSrv);
	WSACleanup();

客户端:

1. 加载套接字库(WSAStartup)

2. 创建用于通信的套接字(socket)

3. 利用创建的套接字与服务器进行通信(sendto/recvfrom)

4. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)

	// 加载套接字库
	WSAData wsaData;
	if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
	{
		return;
	}
	if(1 != LOBYTE(wsaData.wVersion) ||
	   1 != HIBYTE(wsaData.wVersion))
	{
		// 终止对套接字库的使用
		WSACleanup();
		return;
	}

	// 创建套接字
	SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);

	// 直接利用创建的套接字向SOCKADDR指定的服务器发送数据
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addrSrv.sin_port = htons(6000);
	sendto(sockClient, "Hello", strlen("Hello")+1, 0,
		(SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

	// 关闭套接字,并终止套接字库的使用
	closesocket(sockClient);
	WSACleanup();

三、注意事项

编写基于socket网络应用程序时,需事先做到两件事:

1. 包含头文件:Winsock2.h

2. 添加依赖项:ws2_32.lib

基于TCP协议网络应用程序和基于UDP协议的网络应用程序的区别在于:

1. TCP服务器需要在接收到客户端连接请求后,才能与之通信;而UDP服务器直接利用绑定到本地的套接字等待接收数据,接收到数据后才知道客户端的地址信息

2. TCP客户端需要在与服务器建立链接后,才能与之通信;而UDP客户端直接利用绑定到本地的套接字向服务器发送数据,指定的服务器地址信息可以任意指定,因此不确定能不能被接收


版权声明: 此文为本站源创文章[或由本站编辑从网络整理改编],
转载请备注出处:
[CSDN软件开发网] http://blog.csdn.net/mowenliunian/article/details/53341402
[若此文确切存在侵权,请联系本站管理员进行删除!]


--THE END--