Try again349 2021-11-15 05:02 采纳率: 25%
浏览 112

linux中UDP套接字客户端端口port为什么为0?


#include<unistd.h>
#include<cstdio>
#include<string>
#include<sys/socket.h>//套接字接口信息
#include<netinet/in.h>//包含地址结构信息
#include<arpa/inet.h>//字节序转换接口


class UdpSocket
{
public:
    UdpSocket():_sockfd(-1){}
    bool Socket()//创建套接字
    {
        //socket(地址域,套接字类型,协议类型)
        _sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
        if(_sockfd<0){
            perror("socket error!");
            return false;
        }
        return true;
    }
    bool Bind(const std::string &ip,uint16_t port)//为套接字绑定地址信息
    {
        //定义IPV4地址结构  struct sockaddr_in
        struct sockaddr_in addr;
        addr.sin_family=AF_INET;
        addr.sin_port=htons(port);//htons将主机字节序短整型数据转换为网络字节序数据
        addr.sin_addr.s_addr=inet_addr(ip.c_str());//将字符串IP地址转换为网络字节序
        //bind(描述符,地址信息,地址信息长度)
        socklen_t len=sizeof(struct sockaddr_in);
        int ret=bind(_sockfd,(struct sockaddr*)&addr,len);
        if(ret<0){
            perror("bind error!");
            return false;
        }
        return true;
    }
    bool Recv(std::string* buf,std::string *ip=nullptr,uint16_t *port=nullptr)//接收数据,获取发送端的地址信息
    {
        //recvfrom(套接字句柄,接收缓存区,数据长度,标识,源端地址,地址长度)
        struct sockaddr_in peer_addr;
        socklen_t len=sizeof(struct sockaddr_in);
        char tmp[4096]={0};
        int ret=recvfrom(_sockfd,tmp,4096,0,(struct sockaddr*)&peer_addr,&len);
        if(ret<0){
            perror("recvfrom error!");
            return false;
        }
        buf->assign(tmp,ret);//assign从指定字符串中截取指定长度的数据放到buf中
        if(port!=nullptr){
            *port=ntohs(peer_addr.sin_port);//网络字节序到主机字节序的转换
        }
        if(ip!=nullptr){
            *ip=inet_ntoa(peer_addr.sin_addr);//网络字节序到字符串IP地址的转换
        }
        return true;
    }
    bool Send(std::string& data,std::string& ip,uint16_t port)//发送数据
    {
        //sendto(套接字句柄,数据首地址,数据长度,标识,对端地址信息,地址信息长度)
        struct sockaddr_in addr;
        addr.sin_family=AF_INET;
        addr.sin_port=htons(port);
        addr.sin_addr.s_addr=inet_addr(ip.c_str());
        socklen_t len=sizeof(struct sockaddr_in);
        int ret=sendto(_sockfd,data.c_str(),data.size(),0,(struct sockaddr*)&addr,len);
        if(ret<0){
            perror("sendto error!\n");
            return false;
        }
        return true;
    }
    bool Close()//关闭套接字
    {
        if(_sockfd>0){
            close(_sockfd);
            _sockfd=-1;
        }
        return true;
    }
private:
    int _sockfd;
};

/*********************************************************************/

#include<iostream>
#include<string>
#include"UdpSocket.hpp"

#define CHECK_RET(q)  if((q)==false){return false;}

int main(int argc,char* argv[])
{
    //argc 标识程序运行参数的个数
    // ./udp_srv 192.168.2.2  9000   三个参数
    if(argc!=3){
        std::cout<<"Usage: ./udp_srv ip port"<<std::endl;
        return -1;
    }
    std::cout<<argv[2]<<std::endl;
    uint16_t port=std::stoi(argv[2]);
    std::cout<<"Port: "<<port<<std::endl;
    std::string ip=argv[1];
    std::cout<<"ip: "<<argv[1]<<std::endl;
    UdpSocket srv_sock;
    //创建套接字
    CHECK_RET(srv_sock.Socket());
    //绑定地址信息
    CHECK_RET(srv_sock.Bind(ip,port));
    while(1){
         //接收数据
        std::string buf;
        std::string peer_ip;
        uint16_t peer_port;
        CHECK_RET(srv_sock.Recv(&buf,&peer_ip,&port));//接收对端数据
        std::cout<<"buf: "<<buf<<std::endl;                       
        std::cout<<"peer_ip: "<<peer_ip<<std::endl;
        std::cout<<"peer_port: "<<peer_port<<std::endl;
        std::cout<< "client["<<peer_ip<<":"<<peer_port<<"] say: "<<buf<<std::endl;
        //发送数据
        buf.clear();//清空buf
        std::cout<<"server say: ";
        std::cin>>buf;
        CHECK_RET(srv_sock.Send(buf,peer_ip,peer_port));//回复对端数据
    }
    //关闭套接字
    srv_sock.Close();
    return 0;
}

/****************************************/

#include<iostream>
#include<string>
#include"UdpSocket.hpp"

#define CHECK_RET(q)  if((q)==false) {return -1;}

int main(int argc,char* argv[])
{
    //客户端参数获取的IP地址是服务端绑定的地址,也就是客户端发送数据的目标地址
    if(argc!=3){
        std::cout<<"Usage: ./udp_cli ip port\n";
        return -1;
    }
    std::cout<<argv[1]<<std::endl;
    std::cout<<argv[2]<<std::endl;
    std::string srv_ip=argv[1];
    uint16_t srv_port=std::stoi(argv[2]);
    std::cout<<argv[2]<<std::endl;
    UdpSocket cli_sock;
    //创建套接字
    CHECK_RET(cli_sock.Socket());
    //绑定地址(不推荐)
    while(1){
        //发送数据
        std::cout<<"client say:";
        std::string buf;
        std::cin>>buf;
        CHECK_RET(cli_sock.Send(buf,srv_ip,srv_port));
        //接收数据
        buf.clear();
        CHECK_RET(cli_sock.Recv(&buf));
        std::cout<<"server say: "<<buf<<std::endl;
    } 
    //关闭套接字
    cli_sock.Close();
    return 0;
}

程序可以运行,客户端可以发送信息给服务端,但是服务端回复信息会报发送信息错误---Invalid argument
client[129.31.37.177:0] say: nihao
服务端收到的客户端信息中客户端的端口始终是0,我怀疑是这里出错了。各位帮忙看看,是怎么回事,怎么解决

  • 写回答

1条回答 默认 最新

  • qza2468 2021-11-15 08:30
    关注

    0代表让操作系统来选择一个合适的port

    评论

报告相同问题?

问题事件

  • 创建了问题 11月15日

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog