Linux下的UDP通信

2023-05-16

上一部分大致提了一下UDP通信要用到的API,下面就要开始实际测试了,先搞服务端,再搞客户端。 

Linux环境下的UDP/TCP网络通信API接口函数_abs(ln(1+NaN))的博客-CSDN博客icon-default.png?t=M666https://blog.csdn.net/challenglistic/article/details/125673808?spm=1001.2014.3001.5501


目录

一、服务端

1、创建(服务端)套接字

2、绑定IP和端口号

3、接收来自客户端的数据 

4、给客户端发送数据(响应客户端)

二、客户端

1、创建套接字

2、填写服务器的地址信息

3、从键盘获取内容并发送给服务端

三、测试结果


一、服务端

1、创建(服务端)套接字

使用的函数是socket函数,即告诉编译器,你的服务器的通信方式、通信协议。我们的通信方式就选择网络通信AF_INET,通信协议选择UDP

//1. 创建服务端套接字
int server = socket(AF_INET,SOCK_DGRAM,0);
if(server<0)
{
    std::cerr<<"socket创建失败"<<std::endl;
    return 1;
}

2、绑定IP和端口号

服务器一般都是被动接收其他主机的请求,而且服务器可以有多个网卡,即IP地址。如果服务器希望接收来自多个主机的数据,那么就无需主动绑定IP,但是必须要绑定端口号。因为即便IP有多个,端口一般就一个。

创建套接字的时候,既然选择的通信方式是AF_INET,用于存放服务端地址的数据类型那就是struct sockaddr_in。但是在填入bind函数的时候,bind函数使用的是统一接口,所以需要强转成struct sockaddr* 类型。

//2. 绑定IP端口号
//  a.填充地址信息
struct sockaddr_in local;        
local.sin_family = AF_INET;           //选择协议家族(通信方式)AF_INET
uint16_t port = 8080;
local.sin_port = htons(port);         //绑定端口,因为port是16位int型变量,是主机序列,需要转化为网络字节序
local.sin_addr.s_addr = INADDR_ANY;    //如果是接收绑定指定ip的数据,那就是inet_addr("你的ip")
                                       //如果不指定,那就是INADDR_ANY,表明凡是发送到8080端口的
                                       //数据,你都选择接收,不管是服务器上哪个ip地址收到的

//   b.使用bind函数绑定
int ret = bind(server,(struct sockaddr*)&local,sizeof(local));
if (ret<0)
{
    //说明绑定失败
    std::cerr<<"bind绑定失败"<<errno<<std::endl;
    return 2;
}

3、接收来自客户端的数据 

绑定端口后,现在只需要等待接收来自其他客户端的消息。我们使用recvfrom函数来接收,在接收到数据以后,将收到的信息打印出来。

while (1)
{
    /*********接收来自客户端的数据*********/
    char buffer[1024];                 //用于存放对方发送的数据
    struct sockaddr_in src;            //用于保存对端的地址信息
    socklen_t len = sizeof(src);       //对端地址信息的大小
    recvfrom(server,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&src,&len);
    std::cout<<"client# "<< buffer <<std::endl;
}

4、给客户端发送数据(响应客户端)

接收到数据以后,我们把接收到的数据发回给客户端,一般是做一些处理,再把处理结果发送给客户端。我们使用的是sendto函数,第四个参数是客户端的地址信息,我们上一步正好获取到了客户端的地址信息,这里就可以直接拿来用了。

while (1)
{
    /*********接收来自客户端的数据*********/
    char buffer[1024];                 //用于存放对方发送的数据
    struct sockaddr_in src;            //用于保存对端的地址信息
    socklen_t len = sizeof(src);       //对端地址信息的大小
    recvfrom(server,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&src,&len);
    std::cout<<"client# "<< buffer <<std::endl;
    
    std::string msg = "收到来自客户端的信息:";
    msg.append(buffer);
    sendto(server,msg.c_str(),msg.size(),0,(struct sockaddr*)&src,len);
}

二、客户端

1、创建套接字

客户端也需要套接字来承载地址信息,使用的函数也是socket函数

//创建客户端套接字
int client = socket(AF_INET,SOCK_DGRAM,0);
if(client<0){
    std::cerr << "socket创建失败" << std::endl;
    return 1;
}

2、填写服务器的地址信息

在上一篇讲bind函数的用法时,提到这个问题,客户端无需显式的绑定端口号,假设你绑定的端口号为40,然而你并不知道40号端口是否被其他应用程序占用。因此,一般客户端无需显式的绑定端口,绑定端口的任务就交给OS,它最清楚哪个端口没有被占用。

我们需要做的是准备好服务器的地址信息,以用于下面的sendto函数

 //客户端要给谁发??
 struct sockaddr_in dst;
 dst.sin_family = AF_INET;
 dst.sin_port = htons(8080);            //服务器的端口号
 dst.sin_addr.s_addr = inet_addr("124.222.215.205");   //服务器的ip地址

3、从键盘获取内容并发送给服务端

while (1)
{
    //从键盘获取内容
    std::string msg;
    std::cout<<"client# ";
    std::cin>>msg;
    
    //向服务器发送数据
    socklen_t len = sizeof(dst);
    sendto(client,msg.c_str(),msg.size(),0,(struct sockaddr*)&dst,len);

    char buffer[1024];
    //接收服务器做出的响应
    int ret = recvfrom(client,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&dst,&len);
    if(ret>0){
      std::cout<<"server# "<< buffer <<std::endl;
    }                                     
}

三、测试结果

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux下的UDP通信 的相关文章

随机推荐