2016-11-15 1 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 

서버 코드 :

#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

, 당신 초기화 실패 fromlen에 전화하기 전에 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

좋은 catch dbush. @ 밀로스 - 당신은 이것을 위해 컴파일러 경고를보아야 만했다. 그것들을 무시하지 마십시오. –

+0

고마워요! 그것으로 해결되었습니다. –

+0

@BrianMcFarland 예, Makefile에 -Wall을 넣는 것을 잊어 버렸습니다. 그래서 나는 아무 경고도 보지 못했습니다. –

관련 문제