2016-11-15 95 views
2

我正在编写一个简单的说明性UDP服务器客户端。服务器应根据客户端输入计算客户端的网络字节顺序,并将其发送回客户端。我一直试图解决整个一天的这个错误。任何帮助将被认可。这里是服务器启动及输出:C中的UDP服务器/客户端sendto错误:协议不支持地址系列

./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 

Server代码:

#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; 
} 
+0

该服务器收到的客户端sin_family对于AF_INET应为2。但是出于某种原因,这是搞砸了,我无法修复它,因为如果我尝试用AF_INET覆盖它,它会让我发送无效的参数错误。 –

回答

3

在服务器中,你未能初始化在致电sendto之前拨打。结果,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); 
+0

漂亮的dbush。 @Milos - 你应该看到一个编译器警告这个。不要忽视这些。 –

+0

谢谢!这解决了它。 –

+0

@BrianMcFarland是的,忘了把它放在Makefile中,这就是为什么我没有看到警告。 –

相关问题