socket 编程(六) windows udp

本文提供了一个 Windows 平台上的 UDP 通信示例,包括服务器端与客户端的实现细节。该示例展示了如何使用 Winsock 库进行 UDP 数据包的发送与接收,并通过具体的 C 语言代码解释了绑定、监听及数据交互的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

windows udp demo

server:

// win_tcp_server.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <Ws2tcpip.h>
#include <Windows.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)

#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)

int main(int argc,char *argv[])
{
	// 加载套接字库
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	// Winsock库版本,低字节代表主版本,高字节代表副版本
	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		return -1;
	}
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		//终止对winsock库的使用
		WSACleanup();
		return -1;
	}

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

	//************绑定到本机地址和端口***********
	SOCKADDR_IN addrSrv;//本机地址结构体信息,除了sin_family,其它字段都需要采用网络字节序
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//htonl转换为网络字节序,转换的是u_long类型
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(6000);//htons转换为网络字节序,转换的是u_short类型

	// recvfrom 出现10054的错误
	DWORD  dwByteReturned = 0;
	BOOL bNewBehavior = FALSE;
	DWORD status;
	status = WSAIoctl(sockSrv, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwByteReturned, NULL, NULL);
	// 绑定
	int ret = bind(sockSrv, (SOCKADDR*)& addrSrv, sizeof(addrSrv));
	if (!ret) {
		printf("bind success\n");
	}
	else {
		printf("bind ret %d\n",ret);
		return ret;
	}

	ret = 1;
	while (ret > 0) 
	{
		char sendbuf[1500] = { 0 };
		SOCKADDR_IN fromaddr;
		char fromaddrstr[40];
		int fromaddrlen = sizeof(SOCKADDR_IN);
		ret = recvfrom(sockSrv, sendbuf, sizeof(sendbuf), 0, (SOCKADDR*)&fromaddr, &fromaddrlen);
		if (ret <= 0)
		{
			int er = GetLastError();
			printf("ret %d,error 0x%x,%d\n", ret, er, er);
		}
		else
		{
			inet_ntop(AF_INET, &fromaddr.sin_addr, fromaddrstr, sizeof(fromaddrstr));
			printf("ret %d,recv from %s:%d %s\n", ret, fromaddrstr, ntohs(fromaddr.sin_port), sendbuf);

			strcat(sendbuf, " res from server");
			sendto(sockSrv, sendbuf, (int)strlen(sendbuf), 0, (struct sockaddr*) & fromaddr, sizeof(struct sockaddr));
		}
	}

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

	return 0;
}

client:

// win_tcp_client.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <stdio.h>
#include <stdlib.h>
#include <Ws2tcpip.h>
#include <windows.h>
#include <winsock.h>
#include <string.h>

#pragma comment( lib, "ws2_32.lib" )
#pragma warning(disable:4996)

int main(int argc, char* argv[])
{
	// 加载套接字库
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	// Winsock库版本,低字节代表主版本,高字节代表副版本
	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		return -1;
	}
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		//终止对winsock库的使用
		WSACleanup();
		return -1;
	}

	const char* ipstr = "127.0.0.1";
	SOCKET clientSock;
	SOCKADDR_IN ServerAddr = { 0 };

	clientSock = socket(AF_INET, SOCK_DGRAM, 0);

	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(6000);
	ServerAddr.sin_addr.s_addr = inet_addr(ipstr);

	int ret = 1;
	int i = 0;
	while (ret)
	{
		char buf[1500] = { 0 };
		sprintf(buf,"<%d> msg to server",i++);
		ret = sendto(clientSock, buf, (int)strlen(buf), 0, (struct sockaddr*) & ServerAddr, sizeof(struct sockaddr));
		if (ret <= 0) {
			printf("sendto err,ret %d,error %d",ret,GetLastError());
		}

		SOCKADDR_IN fromaddr;
		char fromaddrstr[40];
		int fromaddrlen = sizeof(SOCKADDR_IN);
		memset(buf, 0, sizeof(buf));
		ret = recvfrom(clientSock, buf, sizeof(buf), 0, (SOCKADDR*)& fromaddr, &fromaddrlen);
		if (ret > 0)
		{
			inet_ntop(AF_INET, &fromaddr.sin_addr, fromaddrstr, sizeof(fromaddrstr));
			printf("recv from %s len %d,%s\n", fromaddrstr,ret,buf);
		}
		
		Sleep(3000);
	}

	closesocket(clientSock);
	WSACleanup();
}

运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值