UDP基本应用及广播案例

目录

UDP客户端服务端模型

数据传输

发送数据

接受数据

服务端程序代码

客户端程序代码

广播

广播之接受者

广播之发送者

UDP客户端服务端模型

数据传输

发送数据

#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t nbytes, int flag);
  • 返回: 成功返回发送字节数,出错返回-1。
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flag);
  • 返回: 成功返回发送字节数,出错返回-1。
ssize_t sendto(int sockfd, const void *buf, size_t nbytes, int flag,
                const struct sockaddr *destaddr, socklen_t destlen);
  • 返回: 成功返回发送字节数,出错返回-1。
struct msghdr{
    void *msg_name; /*optional address*/
    socklen_t msg_namelen; /*address size in bytes*/
    struct iovec *msg_iov; /*array of I/O buffers*/
    int msg_iovlen; /*number of elements in array */
    void *msg_control; /*ancillary data*/
    socklen_t msg_controllen; /*number of ancillary bytes*/
    int msg_flags; /*flags for received message*/
}

接受数据

#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t nbytes, int flag);
ssize_t recvfrom(int sockfd, void *restrict buf, size_t len, int flag,
                struct sockaddr *restrict addr, socklen_t *restrict addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flag);
  • 返回: 返回消息的字节数,无消息返回0,出错返回-1

服务端程序代码

int sockfd; 
void sig_handler(int signo)
{
	if(signo==SIGINT)
	{
		printf("server close\n"); 
		close(sockfd); 
		exit(1);
	}
}

//输出客户端的信息
void out_addr(struct sockaddr_in* clientaddr)
{
	char ip[16];
	memset(ip,0,sizeof(ip));
	inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr,ip, sizeof(ip));
	int port=ntohs(clientaddr->sin_port);
	printf("client:%s(%d)\n", ip, port);
}

//和客户端进行通信
void do_service(int fd)
{
	struct sockaddr_in clientaddr;
	socklen_t len = sizeof(clientaddr);
	
	char buffer[1024];
	memset(buffer, 0, sizeof(buffer));
	
	//接受客户端的数据报文
	if(recvfrom(sockfd,buffer, sizeof(buffer), 0,
				(struct sockaddr*)&clientaddr, &len)<0)
	{
		perror("recvfrom error");
	}
	else
    {		
		out_addr(&clientaddr);
		printf("client send info:%s\n", buffer);
		
		//向客户端发送数据报文
		long int t =time(0);
		char*ptr = ctime(&t);
		
		size_t size = strlen(ptr)*sizeof(char);
		if(sendto(sockfd, ptr, size, 0, \
			(struct sockaddr*)&clientaddr, len)<0)
		{
			perror("sendto error"); 			
		}
	}
}

int main(int argc, char *argv[])
{
	if(argc<2)
	{
		printf("usage:%s port\n",argv[0]); 
		exit(1); 
	}
	
	if(signal(SIGINT, sig_ handler) == SIG_ERR)
	{
		perror("signal sigint error"); 
		exit(1);
	}
	
	/*步骤1:创建 socket*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0)
	{
		perror("socket error");
		exit(1);
	}

	int ret;
	int opt=1;
	//设置套接字选项
	if((ret=setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, \
						sizeof(opt)))<0)
	{
		perror("setsockopt error");
		exit(1);
	}
	
	/*步骤2:调用bind函数对socket和地址进行绑定*/
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;//IPV4
	serveraddr.sin_port = htons(atoi(argv[1]));//port 
	serveraddr.sin_addr.s_addr = INADDR_ANY;//ip 
	
	if(bind(sockfd, (struct sockaddr*)&serveraddr, \
					sizeof(serveraddr))<0)
	{
		perror("bind error");
		exit(1);
	}

	/*步骤3:和客户端进行双向的数据通信*/
	while(1){
		do_service();
		return 0;
	}	
}

客户端程序代码

int main(int argc,char *argv[])
{
	if(argc < 3)
	{
		printf("usage:%s ip port\n", argv[0]); 
		exit(1);
	}

	/*步骤1:创建 socket*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0)
	{
		perror("socket error");
		exit(1);
	}

	/*步骤2:调用recvfrom和sendto等函数
	*和服务器端双向通信
	*/
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;//IPV4
	serveraddr.sin_port = htons(atoi(argv[1]));//port 
	serveraddr.sin_addr.s_addr = INADDR_ANY;//ip 

	if(connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
	{
		perror("connect error"); 
		exit(1);
	}

	char buffer[1024] = "Hello world!";
	//向服务器端发送数据报文
	//if(sendto(sockfd, buffer, sizeof(buffer), 0,\
	//		(struct sockaddr*)&serveraddr,sizeof(serveraddr)) < 0)
	if(sendto(sockfd, buffer, sizeof(buffer), 0) < 0)
	{
		perror("sendto error");
		exit(1);
	}
	else
	{
		//接受服务器端发送的数据报文
		memset(buffer, 0, sizeof(buffer));
		size_t size;
		
		if(recv(sockfd, buffer, sizeof(buffer), 0) <0 )
		{
			perror("recv error");
			exit(1);
		}
		else
		{
			printf("%s",buffer); 			
		}
	}
	close(sockfd);
	
	return 0;
}

广播

  • SO_BROADCAST 选项控制着UDP套接字是否能够发送广播数据报,选项的类型为int,非零意味着“是”,注意,只有UDP套接字可以使用这个选项,TCP是不能使用广播的。
int opt = 1;
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
//错误处理
}
if(setsockopt(sockfd, SOL_SOCKET,
    SO_BROADCAST, &opt, sizeof(opt)) < 0)
{
//错误处理
}

广播之接受者

int sockfd; 
void sig_handler(int signo)
{
	if(signo==SIGINT)
	{
		printf("server close\n"); 
		close(sockfd); 
		exit(1);
	}
}

int main(int argc, char *argv[])
{
	if(argc<2)
	{
		printf("usage:%s port\n",argv[0]); 
		exit(1); 
	}
	
	if(signal(SIGINT, sig_handler) == SIG_ERR)
	{
		perror("signal sigint error"); 
		exit(1);
	}
	
	/*步骤1:创建 socket*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0)
	{
		perror("socket error");
		exit(1);
	}

	/*步骤2:调用bind函数对socket和地址进行绑定*/
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;//IPV4
	serveraddr.sin_port = htons(atoi(argv[1]));//port 
	serveraddr.sin_addr.s_addr = INADDR_ANY;//ip 
	
	if(bind(sockfd, (struct sockaddr*)&serveraddr, \
					sizeof(serveraddr))<0)
	{
		perror("bind error");
		exit(1);
	}

	char buffer[1024]; 
	struct sockaddr_in clientaddr; 
	socklen_t len=sizeof(clientaddr); 
	
	while(1){
		memset(buffer, 0, sizeof(buffer)); 
		memset(&clientaddr, 0, sizeof(clientaddr)); 
		if(recvfrom(sockfd, buffer, sizeof(buffer),0,\
				(struct sockaddr*)&clientaddr, &len)<0)
		{
			perror("recvfrom error"); 
			exit(1);
		} 
		else
		{
			char ip[16]; 
			inet_ntop(AF_INET, &clentaddr.sin_addr.s_addr, ip, sizeof(ip)); 
			int port=ntohs(clientaddr.sin_port); 
			printf("%s(%d):%s\n", ip, port, buffer);
		}
	}	
	close(sockfd);	
	return 0;	
}

广播之发送者

int sockfd; 

int main(int argc, char *argv[])
{
	if(argc<2)
	{
		printf("usage:%s port\n", argv[0]); 
		exit(1); 
	}
	
	/*步骤1:创建 socket*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0)
	{
		perror("socket error");
		exit(1);
	}

	int opt=1;//采用广播方式发送
	setsockopt(sockfd, SOL_SOCKET,SO_BROADCAST, &opt, sizeof(opt));
	
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(serveraddr));
	serveraddr.sin family=AF_INET;
	serveraddr.sin_port = htons(atoi(argv[2]));
	inet_pton(AF_INET, argv[1], &serveraddr.sin_addr.s_addr);
	
	printf("I will broadcast...\n"); 
	char * info="hello iotek"; 
	size_t size=strlen(info)* sizeof(char);
	
	if(sendto(sockfd, info, size,0,
			(struct sockaddr*)&serveraddr, sizeof(serveraddr))<0)
	{ 
		perror("sendto error"); 
		exit(1);
	} 
	else
	{
		printf("boradcast success\n");
	}
	
	close(sockfd);
	
	return 0;	
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值