Linux网络编程UDP

UDP通信中的客户端不必与服务器端建立连接,而是直接使用发送函数给服务器发送数据,调用发送函数时要指明目的地址。

事实上,对于UDP来说,并没有严格的服务器和客户端之分

UDP 服务流程

1、UDP服务器通过socket()函数创建套接字,获得套接字描述符

2、UDP服务器调用bind()函数绑定IP地址和端口绑定

3、此时UDP就可以调用recvfrom()函数阻塞的等待数据到来

4、对于客户端,只需要调用socket()函数创建套接字描述符,然后用sendto发送数据即可,调用sendto时要指定服务器的地址和端口。

5、服务器接受到来自客户端的数据后,就会得到客户端的IP地址和端口号等信息,此时就可以用sendto给客户端发消息。

6、结束通信后调用close()关闭套接字描述符

显然,当客户端调用bind函数后,也可作为”服务器“使用。

 

int socket(int domain,int type,int protocol);

参数:1、指明所用协议族 常用的有AF_INET    AF_INET6  AF_LOCAL  AF_ROUTE

      在TCP连接中一般使用AF_INET表示用ipv4和16位端口号

   2、套接字类型。SOCK_STREAM:TCP   SOCK_DGRAM:UDP   SOCK_RAW:允许对底层访问

   3、协议类别。可以为0让系统自动选择

返回值若小于0说明发生错误,否则返回一个值表示创建套接字,类似每个人的身份证号一样,

之后都用套接字描述符来形容这个值

 

int bind(int sockfd,const struct sockaddr*,socklen_t addrlen)

参数:1、套接字描述符

   2、协议地址,用于指定协议族、端口和IP地址

   3、第二个参数的长度

发生错误返回-1,绑定成功返回0; 该函数用于将某个套接字与协议地址关联起来

 

int sendto(int sockfd,const void *msg, int len,unsigned int flags,struct sockaddr *dst_addr,int addrlen)

参数:1、套接字描述符

   2、待发送数据缓冲区

   3、第二个参数的长度

   4、0个或多个标志的组合体,可直接设置为0 或用“|”连在一起。

    MSG_DONTWAIT:非阻塞操作

    MSG_DONTROUTE:告知网际层协议,目的主机在网络,不需要查找路由表

    MSG_NOSIGNAL:动作不愿被SIGPIPE信号中断

    MSG_OOB:表示接受到需要优先处理的数据

   5、数据发送目的地址

   6、第五个参数的长度

用于非可靠数据发送,成功返回实际发送字节数,失败返回-1

 

int recvfrom(int sockfd,void *buf,size_t nbytes,int flags,struct sockaddr *from,socklen_t *addrlen)

参数:1、套接字描述符

   2、接受缓冲区

   3、第二个参数的大小

   4、0个或多个标志的组合体,可直接设置为0 或用“|”连在一起。

    MSG_DONTWAIT:非阻塞操作

    MSG_DONTROUTE:告知网际层协议,目的主机在网络,不需要查找路由表

    MSG_NOSIGNAL:动作不愿被SIGPIPE信号中断

    MSG_OOB:表示接受到需要优先处理的数据

   5、用于存储数据来源的目的地址

   6、第五个参数的长度

非可靠数据传输中用于数据的接受,成功返回接受数据的字节数,失败返回-1

 

服务器:

 1 #include<iostream>
 2 #include<arpa/inet.h>
 3 #include<stdio.h>
 4 #include<string.h>
 5 #include<sys/socket.h>
 6 #include<sys/types.h>
 7 #include<netinet/in.h>
 8 #include<unistd.h>
 9 using namespace std;
10 
11 int main()
12 {
13     struct sockaddr_in addr,recvaddr;
14     socklen_t len=sizeof(recvaddr);
15     int sockfd,op;
16     char buf[512];
17 
18     sockfd=socket(AF_INET,SOCK_DGRAM,0);
19     if(sockfd<0)
20     {
21         cout<<"socket error"<<endl;
22         return -1;
23     }
24 
25     addr.sin_family=AF_INET;
26     addr.sin_port=htons(2501);
27     addr.sin_addr.s_addr=htons(INADDR_ANY);
28 
29     op=bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
30     if(op<0)
31     {
32         cout<<"bind error"<<endl;
33         return -1;
34     }
35 
36     recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&recvaddr,&len);
37     cout<<"recv data from "<<ntohs(recvaddr.sin_port)<<" :"<<buf<<endl;
38 
39     char buff[512]="1234567890987654321";
40     sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&recvaddr,len);
41     return 0;
42 }

 

客户端:

 1 #include<sys/socket.h>
 2 #include<sys/types.h>
 3 #include<iostream>
 4 #include<stdio.h>
 5 #include<stdlib.h>
 6 #include<string.h>
 7 #include<netinet/in.h>
 8 #include<arpa/inet.h>
 9 using namespace std;
10 
11 int main()
12 {
13     int sockfd;
14     int op;
15     struct sockaddr_in addr,saddr;
16     socklen_t len=sizeof(saddr);
17     int i,j;
18 
19     sockfd=socket(AF_INET,SOCK_DGRAM,0);
20     if(sockfd<0)
21     {
22         cout<<"socket error"<<endl;
23         return -1;
24     }
25 
26     addr.sin_family=AF_INET;
27     addr.sin_port=htons(2501);
28     addr.sin_addr.s_addr=htons(INADDR_ANY);
29 
30     char buff[512]="0987654321234567890";
31     sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&addr,sizeof(addr));
32 
33     char buf[512]="";
34     recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&saddr,&len);
35     cout<<"recv data from "<<ntohs(saddr.sin_port)<<" :"<<buf<<endl;
36 
37     return 0;
38 }

参考书籍——《Linux网络编程》

 

Linux网络编程UDP

上一篇:vim操作命令


下一篇:如何修改SAP UI5本地库文件