网络编程udp通讯

本文详细介绍了UDP协议的通信流程,包括从创建套接字、绑定、收发信息到关闭套接字的步骤。特别强调了UDP的单向通讯和双向通讯的实现,以及如何进行UDP广播。同时,对比了UDP与TCP在连接性和可靠性上的区别,并提供了IP地址配置的相关知识。
摘要由CSDN通过智能技术生成

  1.udp流程
          谁先发送,谁就是发送端
                发送端                                         接收端
          创建套接字socket                    创建套接字socket
          绑定bind                                 绑定bind
          收发信息sendto/recvfrom      收发信息sendto/recvfrom
          关闭套接字close                      关闭套接字close
   
    2.相关的接口函数
             (1)发送信息
                 ssize_t sendto(int socket,void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
                              返回值:发送的字节数
                                           -1
                                 参数:前面四个参数跟send一模一样
                                           dest_addr --》存放对方的ip和端口号(需要我们自己主动填写)
                                           dest_len --》地址结构体的大小
            (2)接收信息
               ssize_t recvfrom(int socket, void *buffer, size_t length,int flags, struct sockaddr *address, socklen_t *address_len);
                            返回值:接收的字节数
                                         -1
                               注意:recv函数跟recvfrom是不一样的,recv如果对方断开连接,recv不再阻塞,然后返回0
                                                                                            recvfrom如果对方退出,依然阻塞,不受任何影响
                               参数:前面四个参数跟recv一模一样
                                         address --》存放对方的ip和端口号(不需要我们自己主动填写,接收信息成功,recvfrom函数会自动把发送信息的那个主机的ip和端口号填写到这个变量地址中)
                                        address_len  --》地址结构体的大小  要求是指针

     3.udp广播
             (1)概念
                          发送给局域网中所有在线的主机 
                          比如:咱们这个教室192.168.26.xxxx
                                                        192.168.26 --》网段/网络号(区分不同的局域网)
                                                        xxxx --》主机号(区分同一个局域网中的不同主机)
                                    主机号取值范围正常:0---255之间,但是0不使用,255作为广播专用地址
            (2)实现流程
                     广播发送端                                         广播接收端
          创建套接字socket                                   创建套接字socket
          绑定bind                                                绑定bind
          设置套接字的属性为可以广播
          发送广播信息                                          接收广播信息recvfrom
          关闭套接字close                                     关闭套接字close
            (3)如何设置套接字的属性为可以广播
                   int on=1;
       setsockopt(udpsock,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));
           (4)如果使用udp广播,bind的时候不可以使用具体的ip,必须使用系统的宏定义INADDR_ANY
                       INADDR_ANY的含义:自动匹配本地主机上的任意一个ip地址
                       bindaddr.sin_addr.s_addr=htonl(INADDR_ANY);

     4.理论知识
            (1)ip地址分类  A B C D四类地址
                                 见图示
            (2)tcp和udp区别
                           tcp:有连接的可靠的通信方式
                           udp:无连接的不可靠的通信方式
                           有连接和无连接:
                                   tcp通信双方在正式通信之前,必须经历三次握手(客户端跟服务器之间互相确认身份),确定双方的身份以后才能通信
                                   udp通信双方在正式通信之前,没有三次握手这个说法,也不需要确定对方的身份
                           可靠和不可靠(相对的)
                                   tcp不容易丢失数据包,支持错误重传,错误校验(用于通信要求高的场合)
                                   udp网络拥堵的时候,很容易丢失数据包,不支持错误校验,重传, udp用于通信要求不高的场合(视频点播)
                                  
            (3)配置ip地址
                      方法一:图形用户界面配置
                                          照着window的信息去配置,只有主机号不同,其他的照抄
                      方法二:使用配置文件配置
                                         /etc/network/interfaces这个文件
                                            auto lo
                                            iface lo inet loopback

                                           auto ens33
                                           iface ens33 inet static
                                           address 192.168.26.xxxx
                                           gateway 192.168.26.1      //网关
                                           netmask 255.255.255.0    //子网掩码
                                           dns-nameservers  202.96.134.133  //DNS服务器

 udp单向通讯

#include "myhead.h"

int main()
{
	int udpsock;
	int ret;
	char sbuf[100];
	//定义ipv4地址结构体变量
	struct sockaddr_in bindaddr;
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=AF_INET;
	bindaddr.sin_addr.s_addr=inet_addr("192.168.1.50");  //发送端自己的ip地址
	bindaddr.sin_port=htons(10001);                       //发送端的端口号
	
	//定义ipv4地址结构体变量存放对方的ip和端口号
	struct sockaddr_in serveraddr;
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family=AF_INET;
	serveraddr.sin_addr.s_addr=inet_addr("192.168.1.50");  //对方的ip地址
	serveraddr.sin_port=htons(20000);  //对方的端口号
	
	//创建udp套接字 
	udpsock=socket(AF_INET,SOCK_DGRAM,0);
	if(udpsock==-1)
	{
		perror("创建失败!\n");
		return -1;
	}
	
	//取消端口绑定的限制
	int on=1;
	setsockopt(udpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
	
	//绑定
	ret=bind(udpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
	if(ret==-1)
	{
		perror("绑定ip和端口号失败!\n");
		return -1;
	}
	
	//直接开始聊天,发送信息了
	while(1)
	{
		bzero(sbuf,100);
		printf("请输入要发送的内容:\n");
		scanf("%s",sbuf);
		sendto(udpsock,sbuf,strlen(sbuf),0,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
	}
}

#include "myhead.h"

int main()
{
	int udpsock;
	int ret;
	char sbuf[100];
	//定义ipv4地址结构体变量
	struct sockaddr_in bindaddr;
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=AF_INET;
	bindaddr.sin_addr.s_addr=inet_addr("192.168.1.50");  //接收端自己的ip地址
	bindaddr.sin_port=htons(20000);                       //接收端的端口号
	
	//定义ipv4地址结构体变量存放对方的ip和端口号
	struct sockaddr_in serveraddr;
	bzero(&serveraddr,sizeof(serveraddr));
	int addrsize=sizeof(serveraddr);
	
	//创建udp套接字 
	udpsock=socket(AF_INET,SOCK_DGRAM,0);
	if(udpsock==-1)
	{
		perror("创建失败!\n");
		return -1;
	}
	
	//取消端口绑定的限制
	int on=1;
	setsockopt(udpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
	
	//绑定
	ret=bind(udpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
	if(ret==-1)
	{
		perror("绑定ip和端口号失败!\n");
		return -1;
	}
	
	//直接开始聊天,接收信息了
	while(1)
	{
		bzero(sbuf,100);
		recvfrom(udpsock,sbuf,100,0,(struct sockaddr *)&serveraddr,&addrsize);
		printf("%s:%hu的这台主机发送信息过来了:%s\n",inet_ntoa(serveraddr.sin_addr),ntohs(serveraddr.sin_port),sbuf);
	}
}

 udp双向通讯

#include "myhead.h"

int udpsock;
void *recvmsgfrom(void *arg)
{
	char rbuf[100];
	struct sockaddr_in otheraddr;
	int addrsize=sizeof(otheraddr);
	while(1)
	{
		bzero(rbuf,100);
		recvfrom(udpsock,rbuf,100,0,(struct sockaddr *)&otheraddr,&addrsize);
		printf("回复的信息是:%s\n",rbuf);
	}
}
int main()
{
	pthread_t id;
	int ret;
	char sbuf[100];
	//定义ipv4地址结构体变量
	struct sockaddr_in bindaddr;
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=AF_INET;
	bindaddr.sin_addr.s_addr=inet_addr("192.168.16.51");  //发送端自己的ip地址
	bindaddr.sin_port=htons(10001);                       //发送端的端口号
	
	//定义ipv4地址结构体变量存放对方的ip和端口号
	struct sockaddr_in serveraddr;
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family=AF_INET;
	serveraddr.sin_addr.s_addr=inet_addr("192.168.16.51");  //对方的ip地址
	serveraddr.sin_port=htons(20000);  //对方的端口号
	
	//创建udp套接字 
	udpsock=socket(AF_INET,SOCK_DGRAM,0);
	if(udpsock==-1)
	{
		perror("创建失败!\n");
		return -1;
	}
	
	//取消端口绑定的限制
	int on=1;
	setsockopt(udpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
	
	//绑定
	ret=bind(udpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
	if(ret==-1)
	{
		perror("绑定ip和端口号失败!\n");
		return -1;
	}
	
	//创建子线程接收信息
	pthread_create(&id,NULL,recvmsgfrom,NULL);
	//直接开始聊天,发送信息了
	while(1)
	{
		bzero(sbuf,100);
		printf("请输入要发送的内容:\n");
		scanf("%s",sbuf);
		sendto(udpsock,sbuf,strlen(sbuf),0,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
	}
}

#include "myhead.h"
int udpsock;
//定义ipv4地址结构体变量存放对方的ip和端口号
struct sockaddr_in serveraddr;

void *sendtoother(void *arg)
{
	char rbuf[100];
	while(1)
	{
		bzero(rbuf,100);
		printf("请输入要发送的内容!\n");
		scanf("%s",rbuf);
		sendto(udpsock,rbuf,strlen(rbuf),0,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
	}
}
int main()
{
	pthread_t id;
	int ret;
	char sbuf[100];
	//定义ipv4地址结构体变量
	struct sockaddr_in bindaddr;
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=AF_INET;
	bindaddr.sin_addr.s_addr=inet_addr("192.168.16.51");  //接收端自己的ip地址
	bindaddr.sin_port=htons(20000);                       //接收端的端口号
	
	
	bzero(&serveraddr,sizeof(serveraddr));
	int addrsize=sizeof(serveraddr);
	
	//创建udp套接字 
	udpsock=socket(AF_INET,SOCK_DGRAM,0);
	if(udpsock==-1)
	{
		perror("创建失败!\n");
		return -1;
	}
	
	//取消端口绑定的限制
	int on=1;
	setsockopt(udpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
	
	//绑定
	ret=bind(udpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
	if(ret==-1)
	{
		perror("绑定ip和端口号失败!\n");
		return -1;
	}
	
	//创建线程发送信息
	pthread_create(&id,NULL,sendtoother,NULL);
	
	//直接开始聊天,接收信息了
	while(1)
	{
		bzero(sbuf,100);
		recvfrom(udpsock,sbuf,100,0,(struct sockaddr *)&serveraddr,&addrsize);
		printf("%s:%hu的这台主机发送信息过来了:%s\n",inet_ntoa(serveraddr.sin_addr),ntohs(serveraddr.sin_port),sbuf);
	}
}

 udp广播

#include "myhead.h"

int main()
{
	int udpsock;
	int ret;
	char sbuf[100];
	//定义ipv4地址结构体变量
	struct sockaddr_in bindaddr;
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=AF_INET;
	bindaddr.sin_addr.s_addr=htonl(INADDR_ANY);           //绑定本地主机上的任意一个ip地址
	bindaddr.sin_port=htons(10001);                       //发送端的端口号
	
	//定义ipv4地址结构体变量存放对方的ip和端口号
	struct sockaddr_in serveraddr;
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family=AF_INET;
	serveraddr.sin_addr.s_addr=inet_addr("192.168.26.255");  //发送给192.168.26这个局域网中的所有主机
	serveraddr.sin_port=htons(20000);  //对方的端口号
	
	//创建udp套接字 
	udpsock=socket(AF_INET,SOCK_DGRAM,0);
	if(udpsock==-1)
	{
		perror("创建失败!\n");
		return -1;
	}
	
	//取消端口绑定的限制
	int on=1;
	setsockopt(udpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
	
	//绑定
	ret=bind(udpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
	if(ret==-1)
	{
		perror("绑定ip和端口号失败!\n");
		return -1;
	}
	
	//把套接字的属性设置为可以广播
	setsockopt(udpsock,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));
	
	//发送广播信息
	while(1)
	{
		bzero(sbuf,100);
		printf("请输入要发送的广播信息:\n");
		scanf("%s",sbuf);
		sendto(udpsock,sbuf,strlen(sbuf),0,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
	}
}
#include "myhead.h"

int main()
{
	int udpsock;
	int ret;
	char sbuf[100];
	//定义ipv4地址结构体变量
	struct sockaddr_in bindaddr;
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=AF_INET;
	bindaddr.sin_addr.s_addr=htonl(INADDR_ANY);   //绑定本地主机上的任意一个ip地址
	bindaddr.sin_port=htons(20000);               //接收端的端口号
	
	//定义ipv4地址结构体变量存放对方的ip和端口号
	struct sockaddr_in serveraddr;
	bzero(&serveraddr,sizeof(serveraddr));
	int addrsize=sizeof(serveraddr);
	
	//创建udp套接字 
	udpsock=socket(AF_INET,SOCK_DGRAM,0);
	if(udpsock==-1)
	{
		perror("创建失败!\n");
		return -1;
	}
	
	//取消端口绑定的限制
	int on=1;
	setsockopt(udpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
	
	//绑定
	ret=bind(udpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
	if(ret==-1)
	{
		perror("绑定ip和端口号失败!\n");
		return -1;
	}
	
	//接收广播信息
	while(1)
	{
		bzero(sbuf,100);
		recvfrom(udpsock,sbuf,100,0,(struct sockaddr *)&serveraddr,&addrsize);
		printf("%s:%hu的这台主机发送的广播信息是:%s\n",inet_ntoa(serveraddr.sin_addr),ntohs(serveraddr.sin_port),sbuf);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hqb_newfarmer

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值