Linux---UDP通信

一、服务端

1.创建套接字

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

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

使用 man socket 查看函数使用方法  

2.绑定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.填写服务器的地址信息

客户端无需显式的绑定端口号,假设你绑定的端口号为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("*.*.*.*");   //服务器的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;
    }                                     
}

测试结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值