Windows网络编程:Winsock实现UDP通信

在文章Windows网络编程:一文深入理解Winsock里Jungle详细介绍了Winsock的头文件、面向连接的通信(TCP/IP)和无连接的通信(UDP/IP),Windows网络编程:Winsock实现客户端与服务器文件传输(TCP/IP)中Jungle基于Winsock实现了面向连接的通信,即利用TCP/IP协议通信。本文,Jungle将展示利用UDP/IP实现发送端与接收端的通信。

1.接收端

具体步骤和概念在此不再赘述,见Windows网络编程:一文深入理解Winsock

#include <stdio.h>
#include <stdlib.h>

#include <WinSock2.h>
#pragma comment ( lib,"WS2_32.lib" )  

#define RECEIVER_ADDRESS "127.0.0.1"
#define PORT 8000

void transAddrToBuf(SOCKADDR_IN sockAddr, char* buffer)
{
	if (!buffer){
		return;
	}
	sprintf(buffer, "%s:%d", inet_ntoa(sockAddr.sin_addr), ntohs(sockAddr.sin_port));
}

int main()
{
	WSAData wasData;
	SOCKET recvSocket;
	SOCKADDR_IN receiverAddr;
	char recvBuf[1024] = { 0 };
	int recvBufLength = 1024;
	
	SOCKADDR_IN senderAddr;
	memset(&senderAddr, 0, sizeof(senderAddr));
	int senderAddrLength = sizeof(senderAddr);
	char senderInfo[30] = { 0 };

	int ret = -1;

	// 初始化
	WSAStartup(MAKEWORD(2, 2), &wasData);

	// 创建套接字
	// 套接字类型—:UDP/IP-SOCK_DGRAM
	// 协议:UDP-IPPROTO_UDP
	recvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (SOCKET_ERROR == recvSocket){
		printf("Create Socket Error!");
		goto exit;
	}

	// 创建一个SOCKADDR_IN结构,指定接收端地址信息
	receiverAddr.sin_family = AF_INET;   // 使用IP地址族
	receiverAddr.sin_port = htons(PORT); // 端口号
	receiverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	// bind将地址信息和套接字关联
	ret = bind(recvSocket, (SOCKADDR*)&receiverAddr, sizeof(receiverAddr));
	if (0 != ret){
		printf("bind error with ErrorNum %d\n",WSAGetLastError());
		goto exit;
	}

	// 接收数据报
	while (1){
		ret = recvfrom(recvSocket, recvBuf, recvBufLength, 0, (SOCKADDR*)&senderAddr, &senderAddrLength);
		if (ret > 0){
			printf("recv info:");
			transAddrToBuf(senderAddr, senderInfo);
			//printf("%s\n", senderInfo);
			printf("%s\n", recvBuf);
		}
	}

exit:
	closesocket(recvSocket);
	system("pause");
	return 0;
}

2.发送端

#include <stdio.h>
#include <WinSock2.h>
#pragma comment ( lib,"WS2_32.lib" )  

#define RECEIVER_ADDRESS "127.0.0.1"
#define PORT 8000

int main()
{
	WSAData wasData;
	SOCKET sendSocket;
	SOCKADDR_IN receiverAddr;
	int addrLength = 0;
	char sendBuf[1024] = "fengqiangguo";
	int sendBufLength = 1024;
	int ret = 0;

	// 初始化
	WSAStartup(MAKEWORD(2, 2), &wasData);

	// 创建套接字
	// 套接字类型—:UDP/IP-SOCK_DGRAM
	// 协议:UDP-IPPROTO_UDP
	sendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (SOCKET_ERROR == sendSocket){
		printf("Create Socket Error!");
		goto exit;
	}

	// 创建一个SOCKADDR_IN结构,指定接收端地址信息
	receiverAddr.sin_family = AF_INET;   // 使用IP地址族
	receiverAddr.sin_port = htons(PORT); // 端口号
	receiverAddr.sin_addr.S_un.S_addr = inet_addr(RECEIVER_ADDRESS);

	while (1){
		if (gets(sendBuf)){
			ret = sendto(sendSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR *)&receiverAddr, sizeof(receiverAddr));
			if (0 == ret){
				printf("fail to send\n");
			}
			printf("send info: %s\n", sendBuf);
			memset(sendBuf, 0, sizeof(sendBuf));
		}
	}

exit:
	closesocket(sendSocket);
	system("pause");
	return 0;
}

3.测试

 


欢迎关注知乎专栏:Jungle是一个用Qt的工业Robot

欢迎关注Jungle的微信公众号:Jungle笔记

回复“资料”,领取Jungle为您精心准备的41本计算机领域经典书籍!
回复“机器人”,领取四大家族相关的机器人资料大礼包!

 

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个基于Winsock API编程实现基于UDP协议的点对点双向通信的示例代码,其中假设我们有两台计算机,分别为A和B,它们的IP地址分别为192.168.1.2和192.168.1.3。 A端代码: ```c++ #include <iostream> #include <string> #include <cstdio> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") // 链接winsock库 using namespace std; int main() { // 初始化Winsock库 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { cout << "WSAStartup failed!" << endl; return 0; } // 创建套接字 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { cout << "socket failed!" << endl; WSACleanup(); return 0; } // 指定本地地址和端口号 sockaddr_in localAddr; localAddr.sin_family = AF_INET; localAddr.sin_addr.s_addr = inet_addr("192.168.1.2"); localAddr.sin_port = htons(8000); if (bind(sock, (sockaddr*)&localAddr, sizeof(localAddr)) == SOCKET_ERROR) { cout << "bind failed!" << endl; closesocket(sock); WSACleanup(); return 0; } // 向B端发送数据 sockaddr_in remoteAddr; remoteAddr.sin_family = AF_INET; remoteAddr.sin_addr.s_addr = inet_addr("192.168.1.3"); remoteAddr.sin_port = htons(8000); string message = "hello B!"; sendto(sock, message.c_str(), message.length() + 1, 0, (sockaddr*)&remoteAddr, sizeof(remoteAddr)); // 接收B端的回复 char buffer[1024]; int addrLen = sizeof(remoteAddr); int recvLen = recvfrom(sock, buffer, 1024, 0, (sockaddr*)&remoteAddr, &addrLen); if (recvLen > 0) { cout << "received message from B: " << buffer << endl; } // 关闭套接字并清理Winsock库 closesocket(sock); WSACleanup(); return 0; } ``` B端代码: ```c++ #include <iostream> #include <string> #include <cstdio> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") // 链接winsock库 using namespace std; int main() { // 初始化Winsock库 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { cout << "WSAStartup failed!" << endl; return 0; } // 创建套接字 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { cout << "socket failed!" << endl; WSACleanup(); return 0; } // 指定本地地址和端口号 sockaddr_in localAddr; localAddr.sin_family = AF_INET; localAddr.sin_addr.s_addr = inet_addr("192.168.1.3"); localAddr.sin_port = htons(8000); if (bind(sock, (sockaddr*)&localAddr, sizeof(localAddr)) == SOCKET_ERROR) { cout << "bind failed!" << endl; closesocket(sock); WSACleanup(); return 0; } // 接收A端的数据 char buffer[1024]; sockaddr_in remoteAddr; int addrLen = sizeof(remoteAddr); int recvLen = recvfrom(sock, buffer, 1024, 0, (sockaddr*)&remoteAddr, &addrLen); if (recvLen > 0) { cout << "received message from A: " << buffer << endl; } // 向A端回复数据 string message = "hello A!"; sendto(sock, message.c_str(), message.length() + 1, 0, (sockaddr*)&remoteAddr, sizeof(remoteAddr)); // 关闭套接字并清理Winsock库 closesocket(sock); WSACleanup(); return 0; } ``` 在A端运行程序后,它会向B端发送一条消息,B端接收到这条消息后会向A端回复一条消息。在A端程序中,我们使用sendto函数向B端发送消息,并使用recvfrom函数接收B端的回复;在B端程序中,我们使用recvfrom函数接收A端的消息,并使用sendto函数向A端回复消息。两个程序都使用bind函数指定本地地址和端口号,这样才能绑定到正确的网络接口和端口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冯Jungle

您的支持是对我最大的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值