UDP server/client in C - sendto error: Address family not supported by protocol
UDP server/client in C - sendto error: Address family not supported by protocol
我正在编写一个简单的说明性 UDP 服务器客户端。服务器应根据客户端输入计算客户端的网络字节顺序,并将其发送回客户端。我一整天都在尝试修复此错误。任何帮助将不胜感激。这是服务器启动和输出:
./udpserver.out 4545
from.sin_family: 12079
Little Endian
ERROR UDP_SRV_004 - can not send message to client: Address family not supported by protocol
客户端启动:
./udpclient.out localhost 4545
服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#define BUFFER_SIZE 80
static void error(char *msg){
perror(msg);
exit(1);
}
int main(int argc, char ** argv){
int socketfd, portno, fromlen, n, length;
struct sockaddr_in server, from;
char buffer[BUFFER_SIZE];
char response[BUFFER_SIZE];
const char *le = "Little Endian\n";
const char *be = "Big Endian\n";
const char *unk = "Unknown \n";
int cli_family;
if(argc!=2){
fprintf(stderr,"Error starting the client, please start server as: %s port\n", argv[0]);
exit(0);
}
if((socketfd=socket(AF_INET,SOCK_DGRAM,0))<0)
error("ERROR UDP_SRV_001 - can not create socket");
portno=atoi(argv[1]);
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
server.sin_port=htons(portno);
if(bind(socketfd,(struct sockaddr *)&server,sizeof(server))<0)
error("ERROR UDP_SRV_002 - can not bind server address to a socket file descriptor");
bzero(buffer, BUFFER_SIZE);
bzero(response,BUFFER_SIZE);
n=recvfrom(socketfd,buffer,BUFFER_SIZE-1,0,(struct sockaddr *)&from,&fromlen);
if (n<0)
error("ERROR UDP_SRV_003 - can not receive client's message");
cli_family=from.sin_family;
printf("from.sin_family: %d\n", cli_family);
if (buffer[0] == 1 && buffer[1] == 2)
strcpy(response, be);
else if (buffer[0] == 2 && buffer[1] == 1)
strcpy(response, le);
else
strcpy(response, unk);
length=strlen(response);
printf("%s\n",response);
n=sendto(socketfd,response,length,0,(struct sockaddr *)&from,fromlen);
if(n<0)
error("ERROR UDP_SRV_004 - can not send message to client");
return 0;
}
客户代码:
#include <stdio.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#define BUFFER_SIZE 80
static void error(char *msg){
perror(msg);
exit(1);
}
typedef union UNIT{
short s;
char c[sizeof(short)];
}unit;
int main(int argc, char ** argv){
int socketfd, portno, n, length;
struct sockaddr_in server, from;
struct hostent *host;
char buffer[BUFFER_SIZE];
unit un;
un.s=0x0102;
if(argc!=3){
fprintf(stderr,"Error starting the client, please start client as: %s hostname port\n", argv[0]);
exit(0);
}
if((host=gethostbyname(argv[1]))==NULL)
error("ERROR UDP_CLI_001 - no such host defined, please check your /etc/hosts file");
portno=atoi(argv[2]);
if((socketfd=socket(AF_INET,SOCK_DGRAM,0))<0)
error("ERROR UDP_CLI_002 - can not create socket");
bzero((char *)&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(portno);
bcopy((char *)host->h_addr,(char *)&server.sin_addr,host->h_length);
length=sizeof(server);
if(sizeof(short)!=2){
exit(0);
}
n=sendto(socketfd,un.c,strlen(un.c),0,(struct sockaddr *)&server,length);
if(n<0)
error("ERROR UDP_CLI_003 - can not send to server");
bzero(buffer,BUFFER_SIZE);
n=recvfrom(socketfd,buffer,BUFFER_SIZE,0,(struct sockaddr *)&from, &length);
if(n<0)
error("ERROR UDP_CLI_004 - can receive from server");
printf("%s",buffer);
return 0;
}
在服务器中,您未能在调用 sendto
之前初始化 fromlen
。因此,from
未填充。
来自man page:
If src_addr is not NULL, and the underlying protocol provides the
source address, this source address is filled in. When src_addr is
NULL, nothing is filled in; in this case, addrlen is not used, and
should also be NULL. The argument addrlen is a value-result argument,
which the caller should initialize before the call to the size of the
buffer associated with src_addr, and modified on return to indicate
the actual size of the source address. The returned address is
truncated if the buffer provided is too small; in this case, addrlen
will return a value greater than was supplied to the call.
recvfrom
函数试图读取 fromlen
的值,但由于它未初始化,您调用了 undefined behavior。
初始化 fromlen
即可解决问题。
fromlen = sizeof from;
n=recvfrom(socketfd,buffer,BUFFER_SIZE-1,0,(struct sockaddr *)&from,&fromlen);
我正在编写一个简单的说明性 UDP 服务器客户端。服务器应根据客户端输入计算客户端的网络字节顺序,并将其发送回客户端。我一整天都在尝试修复此错误。任何帮助将不胜感激。这是服务器启动和输出:
./udpserver.out 4545
from.sin_family: 12079
Little Endian
ERROR UDP_SRV_004 - can not send message to client: Address family not supported by protocol
客户端启动:
./udpclient.out localhost 4545
服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#define BUFFER_SIZE 80
static void error(char *msg){
perror(msg);
exit(1);
}
int main(int argc, char ** argv){
int socketfd, portno, fromlen, n, length;
struct sockaddr_in server, from;
char buffer[BUFFER_SIZE];
char response[BUFFER_SIZE];
const char *le = "Little Endian\n";
const char *be = "Big Endian\n";
const char *unk = "Unknown \n";
int cli_family;
if(argc!=2){
fprintf(stderr,"Error starting the client, please start server as: %s port\n", argv[0]);
exit(0);
}
if((socketfd=socket(AF_INET,SOCK_DGRAM,0))<0)
error("ERROR UDP_SRV_001 - can not create socket");
portno=atoi(argv[1]);
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
server.sin_port=htons(portno);
if(bind(socketfd,(struct sockaddr *)&server,sizeof(server))<0)
error("ERROR UDP_SRV_002 - can not bind server address to a socket file descriptor");
bzero(buffer, BUFFER_SIZE);
bzero(response,BUFFER_SIZE);
n=recvfrom(socketfd,buffer,BUFFER_SIZE-1,0,(struct sockaddr *)&from,&fromlen);
if (n<0)
error("ERROR UDP_SRV_003 - can not receive client's message");
cli_family=from.sin_family;
printf("from.sin_family: %d\n", cli_family);
if (buffer[0] == 1 && buffer[1] == 2)
strcpy(response, be);
else if (buffer[0] == 2 && buffer[1] == 1)
strcpy(response, le);
else
strcpy(response, unk);
length=strlen(response);
printf("%s\n",response);
n=sendto(socketfd,response,length,0,(struct sockaddr *)&from,fromlen);
if(n<0)
error("ERROR UDP_SRV_004 - can not send message to client");
return 0;
}
客户代码:
#include <stdio.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#define BUFFER_SIZE 80
static void error(char *msg){
perror(msg);
exit(1);
}
typedef union UNIT{
short s;
char c[sizeof(short)];
}unit;
int main(int argc, char ** argv){
int socketfd, portno, n, length;
struct sockaddr_in server, from;
struct hostent *host;
char buffer[BUFFER_SIZE];
unit un;
un.s=0x0102;
if(argc!=3){
fprintf(stderr,"Error starting the client, please start client as: %s hostname port\n", argv[0]);
exit(0);
}
if((host=gethostbyname(argv[1]))==NULL)
error("ERROR UDP_CLI_001 - no such host defined, please check your /etc/hosts file");
portno=atoi(argv[2]);
if((socketfd=socket(AF_INET,SOCK_DGRAM,0))<0)
error("ERROR UDP_CLI_002 - can not create socket");
bzero((char *)&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(portno);
bcopy((char *)host->h_addr,(char *)&server.sin_addr,host->h_length);
length=sizeof(server);
if(sizeof(short)!=2){
exit(0);
}
n=sendto(socketfd,un.c,strlen(un.c),0,(struct sockaddr *)&server,length);
if(n<0)
error("ERROR UDP_CLI_003 - can not send to server");
bzero(buffer,BUFFER_SIZE);
n=recvfrom(socketfd,buffer,BUFFER_SIZE,0,(struct sockaddr *)&from, &length);
if(n<0)
error("ERROR UDP_CLI_004 - can receive from server");
printf("%s",buffer);
return 0;
}
在服务器中,您未能在调用 sendto
之前初始化 fromlen
。因此,from
未填充。
来自man page:
If src_addr is not NULL, and the underlying protocol provides the source address, this source address is filled in. When src_addr is NULL, nothing is filled in; in this case, addrlen is not used, and should also be NULL. The argument addrlen is a value-result argument, which the caller should initialize before the call to the size of the buffer associated with src_addr, and modified on return to indicate the actual size of the source address. The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.
recvfrom
函数试图读取 fromlen
的值,但由于它未初始化,您调用了 undefined behavior。
初始化 fromlen
即可解决问题。
fromlen = sizeof from;
n=recvfrom(socketfd,buffer,BUFFER_SIZE-1,0,(struct sockaddr *)&from,&fromlen);