带你深入浅出之Windows编程:二、史上最简单之UDP服务端-客户端的创建

此为Windows编程的第谈!关注我,带你快速通过Windows编程的学习路线

每一篇的技术点都是很很重要!很重要!很重要!但不冗余!

我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点!

码农不易,各位学者学到东西请点赞支持支持

开始部分:

总:首先,我们要了解流程(根据此图来理解,并记忆此图)

分:

一、服务端:

  1. 初始化Winsock库:使用WSAStartup函数初始化Winsock库。相当于在家里安装电话网络,确保可以打电话。

  2. 创建套接字:使用socket函数创建一个UDP套接字(SOCK_DGRAM)。与TCP不同,UDP使用数据报来发送数据在家里安装一部电话机,这部电话机可以用来拨打电话。

  3. 分配地址和端口:设置服务端的地址和端口。这里使用INADDR_ANY作为IP地址,表示监听所有网络接口上的指定端口。

  4. bind绑定套接字:使用bind函数将套接字绑定到指定的地址和端口。这样,服务端就可以在该端口上接收来自客户端的数据报。相当于给公司的电话机分配一个固定的电话号码,这个号码可以接收来自任何地方的电话。

  5. 等待接收数据:进入一个无限循环,等待客户端发送数据。使用recvfrom函数接收数据。这个函数会填充recvBuf缓冲区,并更新addrCli变量,后者包含了发送数据报的客户端的地址信息。接线员等待听客户说话,记录客户的需求或问题。

  6. 处理接收到的数据:一旦接收到数据,程序将“Hello”其打印到控制台。

  7. 发送响应:使用sprintf_s函数构造一个响应消息,然后将这个响应通过sendto函数发送回客户端。sendto函数需要客户端的地址信息,这正是recvfrom函数提供的。

  8. 关闭套接字:在程序结束时,使用closesocket函数关闭套接字,释放资源。通话结束后,接线员挂断电话,但电话机继续保持接听模式,准备接听下一个客户的电话。

根据上面的步骤,服务端的代码实现如下:

#include<WinSock2.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"ws2_32.lib")

int main()
{
	//1.初始化套接字
	printf("UDPSRV");
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		printf("WSAStartup errorNum = %d\n", GetLastError());
		return err;
	}
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		printf("LOBYTE errorNum = %d\n", GetLastError());
		WSACleanup();
		return -1;
	}

	//2.创建一个套接字 tcp用的是流STREAM udp用的是报文DGRAM
	SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
	if (INVALID_SOCKET == sockSrv)
	{
		printf("socket errorNo = %d\n", GetLastError());
		return -1;
	}

	//3.分配地址和端口
	SOCKADDR_IN addrSrc;
	addrSrc.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrSrc.sin_family = AF_INET;
	addrSrc.sin_port = htons(6001);

	if (SOCKET_ERROR == bind(sockSrv, (SOCKADDR*)&addrSrc, sizeof(SOCKADDR_IN)))
	{
		printf("bind errorNo = %d\n", GetLastError());
		return -1;
	}


	//4.等待接收数据
	SOCKADDR_IN addrCli;//目的套接字的地址族
	int len = sizeof(SOCKADDR_IN);

	char recvBuf[100] = { 0 };
	char sendBuf[100] = { 0 };

	while (1)
	{
		recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrCli,&len);
		cout << recvBuf << endl;

		sprintf_s(sendBuf, 100, "ACK:%s", recvBuf);
		sendto(sockSrv, sendBuf, strlen(sendBuf)+1, 0, (SOCKADDR*)&addrCli, len);
	}

	//5.关闭套接字
	closesocket(sockSrv);
	system("pause");
	return 0;
}

二、客户端:

  1. 初始化Winsock库:使用WSAStartup函数初始化Winsock库。

  2. 创建套接字:使用socket函数创建一个UDP套接字(SOCK_DGRAM)。UDP使用数据报来发送数据,与TCP的流式传输不同。

  3. 分配服务器地址和端口:设置要连接的服务器的地址和端口。在这个例子中,客户端将连接到本地主机(127.0.0.1)上的6001端口。

  4. 发送数据:使用sendto函数将数据发送到服务器。这个函数需要目标地址和端口信息,以及要发送的数据和数据长度。

  5. 接收数据:使用recvfrom函数接收来自服务器的响应。这个函数同样需要目标地址信息(在这个例子中,服务器地址被重复使用),接收缓冲区和缓冲区长度。

  6. 打印接收到的数据:将接收到的数据打印到控制台。

  7. 关闭套接字:使用closesocket函数关闭套接字,释放资源。

客户端跟服务端的构造其实是类似的。

根据上面的步骤,客户端的代码实现如下:

#include<WinSock2.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"ws2_32.lib")

int main()
{
	//1.初始化套接字
	printf("UDPCLI\n");
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		printf("WSAStartup errorNum = %d\n", GetLastError());
		return err;
	}
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		printf("LOBYTE errorNum = %d\n", GetLastError());
		WSACleanup();
		return -1;
	}


	
	//2.创建一个套接字 tcp用的是流STREAM udp用的是报文DGRAM
	SOCKET sockCli = socket(AF_INET, SOCK_DGRAM, 0);
	if (INVALID_SOCKET == sockCli)
	{
		printf("socket errorNo = %d\n", GetLastError());
		return -1;
	}

	//3.分配地址和端口
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(6001);

	int len = sizeof(SOCKADDR_IN);
	char sendBuf[100] = "hello";
	char recvBuf[100] = { 0 };

	//4.发送数据
	sendto(sockCli, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrSrv, len);

	//5.接收数据
	recvfrom(sockCli, recvBuf, 100, 0, (SOCKADDR*)&addrSrv, &len);

	cout << recvBuf << endl;
	closesocket(sockCli);
	system("pause");

	return 0;
}

总:UDP的无连接特性,它允许客户端快速发送数据到服务器,而不需要事先建立连接。同样,服务器可以快速响应客户端的请求,而不需要维护持久的连接状态。

  学习链接:https://xxetb.xetslk.com/s/3Kif2D

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值