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和自己的思路:
看起来你的代码中有几个小问题需要修正:
在函数udp_init()
中,应该将返回值改为套接字文件描述符,而不是void
类型。
在函数msg_server()
中,应该改为初始化发送方的网络信息,而不是接收方的。
在函数receive()
中,应该用指针类型来传递src_addr
的长度,而不是将其强制转换为unsigned int
。
在函数msg_server()
和main()
中,应该将目标IP地址改为对应的网络地址。
另外,你需要注意的一些细节是:在发送消息时,只有客户端需要初始化目标网络信息,而在接收消息时,服务器和客户端都要初始化对方的网络信息;在函数receive()
中,应该用recvfrom()
函数返回的实际数据长度来对接收缓冲区进行清零,而不是使用sizeof()
函数。