C语言 适用于windows的udp通信简单代码实现

只做了最基础的双向收发功能,参考了很多大佬的文章,还有很多不懂的地方,先把代码贴出来大家互相交流吧。

因为不清楚头文件具体内容,乱加了很多,看起来很冗余。

初始化操作可能有几个是多余的,懒得去掉了。

客户端:

#include <sys/stat.h>

#include <fcntl.h>

#include <errno.h>

#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")

#include <sys/types.h>

#include <Ws2tcpip.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <io.h>
#include <process.h>

#define SERVER_PORT 6677
#define ERROR -1

int main()
{
	//启动wsaData服务
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		perror("WSADATA失败");
	}
	
	//描述服务器的socket
	struct sockaddr_in server_addr;

	//指定服务器端的ip,本地测试:127.0.0.1
	//inet_addr()函数,将点分十进制IP转换成网络字节序IP
	//server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

	char buffer[200];

	int udpClientSocket;

	

	//判断socket是否失败
	if ((udpClientSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		printf("socketError = %d\n", WSAGetLastError());
		return ERROR;
	}
	printf("udpClientSocket的值为:%d\n", udpClientSocket);	

	//初始化服务器地址
	memset(&server_addr, 0, sizeof(server_addr));

	//初始化服务器端套接字并用htons和htonl将端口和地址转成网络字节序
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SERVER_PORT);

	//ip可以是本服务器的ip,也可以用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址,自动绑定ip
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

	printf("服务器地址为:%d\n", server_addr.sin_addr.s_addr);
	

	while (1)
	{
		memset(buffer, 0, sizeof(buffer));
		printf("发送消息:");
		scanf("%s", buffer);
		printf("\n");

		socklen_t len = sizeof(struct sockaddr_in);

		//int udpSendto;
		if (sendto(udpClientSocket, buffer, sizeof(buffer), 0, (struct sockaddr*)&server_addr, len) < 0)
		{
			printf("sendtoError = %d\n", WSAGetLastError());
			perror("sendtoError");
			return ERROR;
		}
		memset(buffer, 0, sizeof(buffer));
		//增加退出机制
		if (strcmp(buffer, "quit") == 0)
			break;


		printf("读取消息:");

		//if (recvfrom(udpClientSocket, buffer, sizeof(buffer), 0, NULL, NULL) < 0) 此处后两个参数也可以是NULL
		if (recvfrom(udpClientSocket, buffer, sizeof(buffer), 0, (struct sockaddr*)&server_addr, &len) < 0)
		{
			printf("recvfromError = %d\n", WSAGetLastError());
			return ERROR;
		}
		printf("%s\n", buffer);
		memset(buffer, 0, sizeof(buffer));
		//增加退出机制
		if (strcmp(buffer, "quit") == 0)
			break;

	}
	close(udpClientSocket);
	return 0;
}

服务器端:

#include <sys/stat.h>

#include <fcntl.h>

#include <errno.h>

#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")

#include <sys/types.h>

#include <Ws2tcpip.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <io.h>
#include <process.h>

#define SERVER_PORT 6677
#define ERROR -1

int main()
{
	int udpServerSocket;

	struct sockaddr_in server_addr;

	struct sockaddr_in client_addr;

	//启动wsaData服务
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		perror("WSADATA失败");
	}

	//判断socket是否失败
	if ((udpServerSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		printf("socketError = %d\n", WSAGetLastError());
		return ERROR;
	}
	printf("udpServerSocket的值为:%d\n", udpServerSocket);

	//初始化地址
	memset(&server_addr, 0, sizeof(server_addr));
	memset(&client_addr, 0, sizeof(client_addr));

	//初始化服务器端套接字并用htons和htonl将端口和地址转成网络字节序
	server_addr.sin_family = AF_INET;

	server_addr.sin_port = htons(SERVER_PORT);

	//ip可以是本服务器的ip,也可以用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	//判断bind是否失败
	int udpBind;
	if (udpBind = bind(udpServerSocket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
	{
		printf("bindError = %d\n", WSAGetLastError());
		return ERROR;
	}
	printf("udpBind的值为:%d\n", udpBind);

	while (1)
	{
		printf("监听端口:%d\n", SERVER_PORT);

		char buffer[200];
		memset(buffer, 0, sizeof(buffer));

		printf("读取消息:");

		socklen_t client_addr_len = sizeof(client_addr);
		if (recvfrom(udpServerSocket, buffer, sizeof(buffer), 0, (struct sockaddr*)&client_addr, &client_addr_len) < 0)
		{
			printf("recvfromError = %d\n", WSAGetLastError());
			return ERROR;
		}
		printf("%s\n", buffer);

		//增加退出机制
		if (strcmp(buffer, "quit") == 0)
			break;
		memset(buffer, 0, sizeof(buffer));
		

		printf("发送消息:");
		scanf("%s", buffer);
		printf("\n");

		int udpSendto;
		if (udpSendto = (sendto(udpServerSocket, buffer, sizeof(buffer), 0, (struct sockaddr*)&client_addr, client_addr_len)) < 0)
		{
			printf("sendtoError = %d\n", WSAGetLastError());
			return ERROR;
		}
		memset(buffer, 0, sizeof(buffer));

		//增加退出机制
		if (strcmp(buffer, "quit") == 0)
			break;
	}
	close(udpServerSocket);
	return 0;
}

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UDP组播通信是一种基于UDP协议的多播通信方式,可以在局域网内实现一对多的数据传输。以下是使用C语言实现UDP组播通信的基本步骤: 1. 创建UDP套接字: 使用`socket()`函数创建一个UDP套接字,指定协议族为`AF_INET`,类型为`SOCK_DGRAM`。 2. 设置组播地址和端口: 使用`setsockopt()`函数设置多播组地址和端口,其中IP地址为组播地址,端口为组播监听的端口。 3. 绑定套接字: 使用`bind()`函数将套接字绑定到本地IP地址和指定的端口上。 4. 加入组播组: 使用`setsockopt()`函数设置套接字的`IP_ADD_MEMBERSHIP`选项,将套接字加入到指定的组播组中。 5. 接收组播数据: 使用`recvfrom()`函数从套接字接收组播数据。 6. 发送组播数据: 使用`sendto()`函数将数据发送到指定的组播地址和端口。 下面是一个简单的UDP组播通信的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #define GROUP_ADDR "239.0.0.1" // 组播地址 #define PORT 8888 // 组播端口 int main() { int sockfd; struct sockaddr_in addr; char buffer[1024]; // 创建UDP套接字 sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } // 设置组播地址和端口 memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(GROUP_ADDR); addr.sin_port = htons(PORT); // 绑定套接字 if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 加入组播组 struct ip_mreq mreq; memset(&mreq, 0, sizeof(mreq)); mreq.imr_multiaddr.s_addr = inet_addr(GROUP_ADDR); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { perror("setsockopt failed"); exit(EXIT_FAILURE); } // 接收组播数据 while (1) { memset(buffer, 0, sizeof(buffer)); if (recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL) < 0) { perror("recvfrom failed"); exit(EXIT_FAILURE); } printf("Received data: %s\n", buffer); } // 关闭套接字 close(sockfd); return 0; } ``` 这是一个组播接收端的示例代码,可以接收从同一组播地址和端口发送的数据。你可以根据需要修改代码来实现组播发送端。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值