C语言编程实现udp通信

C语言UDP编程,实现udp通信,找不出问题,求解
这是client.c

#include
#include
#include
#include
#include 
#include 
#include 
#include 
#define N 20
void udp_init(int sockfd1,struct sockaddr_in addr1){
    if(sockfd1<0){
        perror("套接字创建失败");
        exit(0);
    }
    else puts("套接字创建成功");

    //2.绑定套接子,添加网络信息  本机网络信息
    addr1.sin_family=AF_INET;//初始化结构体变量  地址族
    addr1.sin_port=htons(8888);//端口号
    addr1.sin_addr.s_addr=inet_addr("192.168.124.73");
    //初始化完成后可以开始绑定
    int bindret=bind(sockfd1,(struct sockaddr*)&addr1,sizeof(addr1));//该函数返回值为int,成功返回0,失败返回-1,所以定义bindret接收返回值
    if(bindret<0){
        perror("bind error");
        exit(0);
    }
    else puts("bind sucucess");
}

void msg_server(struct sockaddr_in dest_addr1){//添加接收方网络信息    
//初始化接收方网络信息    
    dest_addr1.sin_family=AF_INET;//初始化结构体变量  地址族
    dest_addr1.sin_port=htons(9999);//端口号
    dest_addr1.sin_addr.s_addr=inet_addr("192.168.124.73");
    //sendto(sockfd1,buf,sizeof(buf),0,dest_addr1,sizeof(dest_addr1));
}

void receive(int sockfd1,struct sockaddr_in src_addr1){//接收消息,存放到数组指针
    char buf[N];
    puts("1");
    socklen_t *len=(unsigned int *)sizeof(src_addr1);
    puts("2");
    recvfrom(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&src_addr1,len);
    puts("3");
    printf("buf:%s,src_addr1.sin_port:%u,src_addr1.sin_addr.s_addr:%u\n",buf,src_addr1.sin_port,src_addr1.sin_addr.s_addr);
}

int main(){
    char buf[N];
    int sockfd1=socket(AF_INET,SOCK_DGRAM,0);//函数返回值为int型,所以定义一个int型sockfd套接字文件描述符用来接收返回值
    struct sockaddr_in addr1;//声明一个结构体实例为addr//本机网络信息
    struct sockaddr_in dest_addr1;//声明一个结构体实例为dest_addr1//发送目标的网络信息
    struct sockaddr_in src_addr1;//声明一个结构体实例为src_addr1//接收到的对方的网络信息
    udp_init(sockfd1,addr1);
    msg_server(dest_addr1);
    while(1){
    fgets(buf,sizeof(buf),stdin);
    sendto(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&dest_addr1,sizeof(dest_addr1));
    memset(buf,0,sizeof(buf));
    receive(sockfd1,src_addr1);
    puts("receive cucess");
    }

return 0;
}




这是server.c

#include
#include
#include
#include
#include 
#include 
#include 
#include 
#define N 20
int udp_init(int sockfd1,struct sockaddr_in addr1){
    if(sockfd1<0){
        perror("套接字创建失败");
        exit(0);
    }
    else puts("套接字创建成功");

    //2.绑定套接子,添加网络信息  本机网络信息
    addr1.sin_family=AF_INET;//初始化结构体变量  地址族
    addr1.sin_port=htons(9999);//端口号
    addr1.sin_addr.s_addr=inet_addr("192.168.124.73");
    //初始化完成后可以开始绑定
    int bindret=bind(sockfd1,(struct sockaddr*)&addr1,sizeof(addr1));//该函数返回值为int,成功返回0,失败返回-1,所以定义bindret接收返回值
    if(bindret<0){
        perror("bind error");
        exit(0);
    }
    else puts("bind sucucess");
    return sockfd1;
}

void msg_server(struct sockaddr_in dest_addr1){//添加接收方网络信息    
//初始化接收方网络信息    
    dest_addr1.sin_family=AF_INET;//初始化结构体变量  地址族
    dest_addr1.sin_port=htons(8888);//端口号
    dest_addr1.sin_addr.s_addr=inet_addr("192.168.124.73");
    //sendto(sockfd1,buf,sizeof(buf),0,dest_addr1,sizeof(dest_addr1));
}

void receive(int sockfd1,struct sockaddr_in src_addr1){//接收消息,存放到数组指针
    char buf[N];
    socklen_t *len=(unsigned int *)sizeof(src_addr1);
    recvfrom(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&src_addr1,len);
    printf("buf:%s,src_addr1.sin_port:%u,src_addr1.sin_addr.s_addr:%u\n",buf,src_addr1.sin_port,src_addr1.sin_addr.s_addr);
}

int main(){
    char buf[N];
    int sockfd1=socket(AF_INET,SOCK_DGRAM,0);//函数返回值为int型,所以定义一个int型sockfd套接字文件描述符用来接收返回值
    struct sockaddr_in addr1;//声明一个结构体实例为addr//本机网络信息
    struct sockaddr_in dest_addr1;//声明一个结构体实例为dest_addr1//发送目标的网络信息
    struct sockaddr_in src_addr1;//声明一个结构体实例为src_addr1//接收到的对方的网络信息
    udp_init(sockfd1,addr1);
    msg_server(dest_addr1);
    while(1){
    receive(sockfd1,src_addr1);
    fgets(buf,sizeof(buf),stdin);
    sendto(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&dest_addr1,sizeof(dest_addr1));
    memset(buf,0,sizeof(buf));
    //receive(sockfd1,src_addr1);
    }

return 0;
}




大致看了下你的代码,服务端和客户端问题都差不多。
问题1,udp_init,msg_server 传入struct sockaddr_in时,需要以指针的方式,不然那些地址结构体的值将不会保存;
问题2. socklen_t *len=(unsigned int *)sizeof(src_addr1);recvfrom(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&src_addr1,len);
这样用是不行的,要改成这样:

socklen_t len=sizeof(struct sockaddr_in);
recvfrom(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&src_addr1, &len);

修改后客户端的代码如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define N 20
void udp_init(int sockfd1,struct sockaddr_in *addr1){
    if(sockfd1<0){
        perror("套接字创建失败");
        exit(0);
    }
    else puts("套接字创建成功");
 
    //2.绑定套接子,添加网络信息  本机网络信息
    addr1->sin_family=AF_INET;//初始化结构体变量  地址族
    addr1->sin_port=htons(8888);//端口号
    addr1->sin_addr.s_addr=inet_addr("192.168.124.73");
    //初始化完成后可以开始绑定
    int bindret=bind(sockfd1,(struct sockaddr*)addr1,sizeof(struct sockaddr_in));//该函数返回值为int,成功返回0,失败返回-1,所以定义bindret接收返回值
    if(bindret<0){
        perror("bind error");
        exit(0);
    }
    else puts("bind sucucess");
}
 
void msg_server(struct sockaddr_in *dest_addr1){//添加接收方网络信息    
//初始化接收方网络信息    
    dest_addr1->sin_family=AF_INET;//初始化结构体变量  地址族
    dest_addr1->sin_port=htons(9999);//端口号
    dest_addr1->sin_addr.s_addr=inet_addr("192.168.124.73");
    //sendto(sockfd1,buf,sizeof(buf),0,dest_addr1,sizeof(dest_addr1));
}
 
void receive(int sockfd1,struct sockaddr_in src_addr1){//接收消息,存放到数组指针
    char buf[N];
    puts("1");
    socklen_t len=sizeof(struct sockaddr_in);
    puts("2");
    recvfrom(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&src_addr1, &len);
    puts("3");
    printf("buf:%s,src_addr1.sin_port:%u,src_addr1.sin_addr.s_addr:%u\n",buf,src_addr1.sin_port,src_addr1.sin_addr.s_addr);
}
 
int main(){
    char buf[N];
    int sockfd1=socket(AF_INET,SOCK_DGRAM,0);//函数返回值为int型,所以定义一个int型sockfd套接字文件描述符用来接收返回值
    struct sockaddr_in addr1;//声明一个结构体实例为addr//本机网络信息
    struct sockaddr_in dest_addr1;//声明一个结构体实例为dest_addr1//发送目标的网络信息
    struct sockaddr_in src_addr1;//声明一个结构体实例为src_addr1//接收到的对方的网络信息
    udp_init(sockfd1,&addr1);
    msg_server(&dest_addr1);
    while(1){
    fgets(buf,sizeof(buf),stdin);
    sendto(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&dest_addr1,sizeof(dest_addr1));
    memset(buf,0,sizeof(buf));
    receive(sockfd1,src_addr1);
    puts("receive cucess");
    }
 
return 0;
}
 

服务端的代码如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define N 20
int udp_init(int sockfd1,struct sockaddr_in *addr1){
    if(sockfd1<0){
        perror("套接字创建失败");
        exit(0);
    }
    else puts("套接字创建成功");
 
    //2.绑定套接子,添加网络信息  本机网络信息
    addr1->sin_family=AF_INET;//初始化结构体变量  地址族
    addr1->sin_port=htons(9999);//端口号
    addr1->sin_addr.s_addr=inet_addr("192.168.124.73");
    //初始化完成后可以开始绑定
    int bindret=bind(sockfd1,(struct sockaddr*)addr1,sizeof(struct sockaddr));//该函数返回值为int,成功返回0,失败返回-1,所以定义bindret接收返回值
    if(bindret<0){
        perror("bind error");
        exit(0);
    }
    else puts("bind sucucess");
    return sockfd1;
}
 
void msg_server(struct sockaddr_in *dest_addr1){//添加接收方网络信息    
//初始化接收方网络信息    
    dest_addr1->sin_family=AF_INET;//初始化结构体变量  地址族
    dest_addr1->sin_port=htons(8888);//端口号
    dest_addr1->sin_addr.s_addr=inet_addr("192.168.124.73");
    //sendto(sockfd1,buf,sizeof(buf),0,dest_addr1,sizeof(dest_addr1));
}
 
void receive(int sockfd1,struct sockaddr_in src_addr1){//接收消息,存放到数组指针
    char buf[N];
    socklen_t len=sizeof(struct sockaddr_in);
    recvfrom(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&src_addr1,&len);
    printf("buf:%s,src_addr1.sin_port:%u,src_addr1.sin_addr.s_addr:%x\n",buf,htons(src_addr1.sin_port),src_addr1.sin_addr.s_addr);
}
 
int main(){
    char buf[N];
    int sockfd1=socket(AF_INET,SOCK_DGRAM,0);//函数返回值为int型,所以定义一个int型sockfd套接字文件描述符用来接收返回值
    struct sockaddr_in addr1;//声明一个结构体实例为addr//本机网络信息
    struct sockaddr_in dest_addr1;//声明一个结构体实例为dest_addr1//发送目标的网络信息
    struct sockaddr_in src_addr1;//声明一个结构体实例为src_addr1//接收到的对方的网络信息
    udp_init(sockfd1,&addr1);
    msg_server(&dest_addr1);
    while(1){
    receive(sockfd1,src_addr1);
    fgets(buf,sizeof(buf),stdin);
    sendto(sockfd1,buf,sizeof(buf),0,(struct sockaddr *)&dest_addr1,sizeof(dest_addr1));
    memset(buf,0,sizeof(buf));
    //receive(sockfd1,src_addr1);
    }
 
return 0;
}
 

参考GPT和自己的思路:

看起来你的代码中有几个小问题需要修正:

  1. 在函数udp_init()中,应该将返回值改为套接字文件描述符,而不是void类型。

  2. 在函数msg_server()中,应该改为初始化发送方的网络信息,而不是接收方的。

  3. 在函数receive()中,应该用指针类型来传递src_addr的长度,而不是将其强制转换为unsigned int

  4. 在函数msg_server()main()中,应该将目标IP地址改为对应的网络地址。

另外,你需要注意的一些细节是:在发送消息时,只有客户端需要初始化目标网络信息,而在接收消息时,服务器和客户端都要初始化对方的网络信息;在函数receive()中,应该用recvfrom()函数返回的实际数据长度来对接收缓冲区进行清零,而不是使用sizeof()函数。