Linux网络编程(socket的udp通信)

目录

  • Linux网络编程(socket的udp通信)
    • 一、udp通信用到的相关函数解析
    • 二、udp通信的编程模型
    • 三、dup通信编程示例
      • 服务器端
      • 客户端

Linux网络编程(socket的udp通信)

UDP是无连接的,即发送数据之前不需要建立连接,它尽最大努力交付,即不保证可靠交付,在一些要求实时性的通信中多有用到如游戏,视频等,UDP是面向报文的,有别于tcp的一对一通信,udp支持一对一、一对多、多对一和多对多的交互通信等。

一、udp通信用到的相关函数解析

int socket(int domain, int type, int protocol);
功能:创建socket对象
type:SOCK_DGRAM 数据报协议 UDP

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:绑定socket和通信地址
sockfd:socket描述符
addr:地址结构体指针,实际传递的是 sockaddr_un或者sockaddr_in 结构体指针,需要把它们统一转换为sockaddr*类型。具体sockaddr_in结构体在socket的本地通信博文中有提到,这里不再赘述。

UDP专属的数据发送接收函数
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
功能:UDP协议发送数据
sockfd:socket描述符
buf:待发送数据内存首地址
len:待发送数据的字节数
flags:是否阻塞 一般写0阻塞即可
dest_addr:通信目标的地址
addrlen:地址结构体的字节数
返回值:成功发送的字节数,0表示通信关闭,-1表示出现错误

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
功能:UDP协议接收数据
sockfd:socket描述符
buf:存储接收数据的缓冲区内存首地址
len:缓冲区的字节数
flags:是否阻塞 一般写0阻塞即可
src_addr:用于存储发送者的地址
addrlen:既是输入,也是输出,既告诉函数当前src_addr结构体的字节数,同时也能实际接收到发送者的地址结构体字节数。
返回值:成功接收到的字节数,0表示通信关闭,-1表示出现错误。

二、udp通信的编程模型

基于UDP通信协议的网络通信编程模型:

   接收端                 发送端
创建socket             创建socket
准备通信地址            准备通信地址
绑定                   ...
接收请求                发送请求
响应请求                接收响应
关闭socket              关闭socket

三、dup通信编程示例

服务器端

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

typedef struct sockaddr* SP;

int main(int argc,const char* argv[])
{
	//	创建socket
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return EXIT_FAILURE;
	}
	
	//	准备本机通信地址
	struct sockaddr_in srv_addr = {},cli_addr = {};
	srv_addr.sin_family = AF_INET;
	srv_addr.sin_port = htons(7788);
    //这里的“xxx.xx.xx.xx”写本机的ip地址,可以用ifconfig命令查看,windows可以用ipconfig查看
	srv_addr.sin_addr.s_addr = inet_addr("xxx.xx.xx.xx");
	socklen_t addrlen = sizeof(srv_addr);

	//	绑定
	if(bind(sockfd,(SP)&srv_addr,addrlen))
	{
		perror("bind");
		return EXIT_FAILURE;
	}

	char buf[4096] = {};
	size_t buf_size = sizeof(buf);

	for(;;)
	{
		//	接收数据和对方的地址
		int ret = recvfrom(sockfd,buf,buf_size,0,(SP)&cli_addr,&addrlen);
		if(0 >= ret)
		{
			printf("网络异常,通信结束!");
			close(sockfd);
			return EXIT_FAILURE;
		}
		printf("from %s recv:[%s] bits:%d\n",
			inet_ntoa(cli_addr.sin_addr),buf,ret);

		//	返回响应
		strcat(buf,"from udpS");
		ret = sendto(sockfd,buf,strlen(buf)+1,0,(SP)&cli_addr,addrlen);
		if(0 >= ret)
		{
			printf("对方网络异常!\n");	
		}
	}
}	

客户端

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

typedef struct sockaddr* SP;

int main(int argc,const char* argv[])
{
	//	创建socket
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return EXIT_FAILURE;
	}
	
	//	准备服务器通信地址
	struct sockaddr_in srv_addr = {};
	srv_addr.sin_family = AF_INET;
	srv_addr.sin_port = htons(7788);
	srv_addr.sin_addr.s_addr = inet_addr("xx.xx.xxx.xxx");//这里写需要通信的ip地址
	socklen_t addrlen = sizeof(srv_addr);

	char buf[4096] = {};
	size_t buf_size = sizeof(buf);

	for(;;)
	{
		printf(">>>");
		scanf("%s",buf);
		if(0 == strcmp(buf,"quit"))
		{
			printf("结束通信!\n");
			close(sockfd);
			return EXIT_SUCCESS;
		}
		int ret = sendto(sockfd,buf,strlen(buf)+1,0,(SP)&srv_addr,addrlen);
		if(0 >= ret)
		{
			printf("网络异常!\n");
			close(sockfd);
			return EXIT_FAILURE;
		}
		//	接收数据和对方的地址
		ret = recvfrom(sockfd,buf,buf_size,0,(SP)&srv_addr,&addrlen);
		if(0 >= ret)
		{
			printf("网络异常,通信结束!");
			close(sockfd);
			return EXIT_FAILURE;
		}
		printf("from %s recv:[%s] bits:%d\n",
			inet_ntoa(srv_addr.sin_addr),buf,ret);

	}
}	

你可能感兴趣的:(网络编程,udp,网络,linux)