2016-11-15 15 views
2

私は簡単なUDPサーバクライアントの例を書いています。サーバーは、クライアントの入力に基づいてクライアントのネットワークバイトオーダーを計算し、それをクライアントに送り返す必要があります。私は今このエラーを1日中修正しようとしています。どんな援助も必要になるでしょう。ここでは、サーバーの起動、出力は次のとおりです。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でそれを上書きしようとすると、無効な引数エラーsendtoを返します。 –

答えて

3

、あなた初期化に失敗しましたへのコールの前に。その結果、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

ニースcatch dbush。 @Milos - これについてコンパイラの警告が見えたはずです。それらを無視しないでください。 –

+0

ありがとう!それがそれを解決しました。 –

+0

@BrianMcFarlandはい、Makefileに-Wallを入れるのを忘れてしまったので、警告が表示されませんでした。 –

関連する問題