2013-03-22 2 views
0

클라이언트에게 메시지를 보내야하고 클라이언트가 옵션으로 응답해야합니다. 나는 클라이언트와 서버가 연결될 때까지 얻지 만, 두 프로그램 모두는 "Segmentation Fault"로 끝납니다. 누구든지이 오류의 의미를 압니까? 누군가가 클라이언트와 서버가 상호 작용할 수있는 코드를 작성하는 방법에 대한 아이디어를 줄 수 있습니까? 클라이언트가 선택한 옵션을받은 후 서버는이를 분석하고 클라이언트에 결과를 다시 보내야합니다.서버에서 클라이언트로 메시지를 보내려고하는 세그먼트 오류

내 코드는 다음과 같습니다

서버

int 
main(int argc, char **argv) 
{ 
    int     listenfd, connfd; 
    socklen_t   len; 
    struct sockaddr_in servaddr, cliaddr; 
    char    buff[MAXLINE]; 
    time_t    ticks; 
    char    message[MAXLINE]="This is the server"; 
    char    temp_scale[2]; 
    char    recvdata[MAXLINE + 1]; 

    listenfd = Socket(AF_INET, SOCK_STREAM, 0); 
    bzero(&servaddr, sizeof(servaddr)); 
    servaddr.sin_family  = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/*----------------------------------------------------*/ 
    servaddr.sin_port  = htons(5555); 

    Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); 
    Listen(listenfd, LISTENQ); 

    for (; ;) 
    { 
     len = sizeof(cliaddr); 
     connfd = Accept(listenfd, (SA *) &cliaddr, &len); 

     printf("Connection from %s, port %d\n", 
       Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)), 
       ntohs(cliaddr.sin_port)); 


     snprintf(message, sizeof(message), "%s\r\n"); 
      Writen(connfd, message, strlen(message)); 
      while ((n = read(connfd, recvdata, MAXLINE)) > 0) 
      { 
      recvdata[n] = 0; /* null terminate*/ 
      if (fputs(recvdata, stdout) == EOF) 
       err_sys("fputs error"); 
      } 
      if (n < 0) 
      err_sys("read error"); 

      Close(connfd); 
    } 
} 

클라이언트

int 
main(int argc, char **argv) 
{ 
    int     sockfd, rd; 
    socklen_t   len; 
    char    recvline[MAXLINE + 1]; 
    struct sockaddr_in servaddr, cliaddr; 
    char scale[2]; 

    /*if (argc != 2) 
     err_quit("usage: a.out <IPaddress>");*/ 

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     err_sys("socket error"); 

    bzero(&servaddr, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_port = htons(atoi(argv[2])); /*port passed through command line*/ 
    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) /*The client translates the server address, passed on the command line*/ 
     err_quit("inet_pton error for %s", argv[1]); 


    if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0) 
     err_sys("connect error"); 

    len = sizeof(cliaddr); 
    Getsockname(sockfd, (SA *) &cliaddr, &len); 
    printf("Local Address is: %s\n", 
      Sock_ntop((SA *) &cliaddr, sizeof(cliaddr))); 

    printf("Iniciando read...\n"); 
    while ((rd = read(sockfd, recvline, MAXLINE)) > 0) 
    { 
     recvline[rd] = 0; /* null terminate*/ 
     if (fputs(recvline, stdout) == EOF) 
      err_sys("fputs error"); 
    } 
    if (rd < 0) 
    err_sys("read error"); 

    printf("Enter option 'A' or 'B'"); 
    send_scale(sockfd); 

    exit(0); 
} 

감사

+0

세그먼트 오류는 금지 된 메모리에 액세스하고 있음을 나타냅니다. 즉, 유효하지 않은 포인터 또는 포인터 또는 어레이 범위를 벗어난 액세스와 관련된 버그가 있습니다. – Lundin

+0

일부 버퍼의 길이가 MAXLINE이지만 일부 버퍼가 MAXLINE + 1 인 이유는 무엇입니까? 코드를 이해하지 못하면 버그와 같은 냄새가 난다. – Lundin

+0

고맙습니다. 문제를 해결하는 방법을 알 수 있습니까? 클라이언트와 서버에서 같은 기능을 사용합니다. 문제가 있습니까? – netfreak

답변

2

서버는 아마 이것 때문에 오류있는 : 그것은 플랫 아웃 잘못

snprintf(message, sizeof(message), "%s\r\n"); // <== no parameters 

. snprintf() 호출에는 char *이 null로 끝나는 문자열로 예상되는 형식 지정자가 있습니다. 아무 것도 전달하지 않습니다. 따라서 스택에서 임의의 값을 가져 와서 포인터로 취급하고 형식화 된 요청을 수행하기 위해 역 참조를 내 보냅니다.

사용중인 API의 세부 사항을 알지 못하면 (이름만으로 표준 BSD 소켓이 아님) 많은 작업을 수행 할 필요가 없습니다. 그것은 도움이 될 경우

+0

WhozCraig에 감사드립니다! 그것은 그 것이 었습니다. 나는 그것을 끈으로 묶고 일했습니다! 이제 독서 부분에 구조체가있어서 서버에서 클라이언트로 메시지를 보내지 만 클라이언트는 메시지를받지 못합니다. 클라이언트와 서버 모두 차단 읽기에 머물러 있습니다 (서버는 클라이언트의 응답을 기대합니다).무슨 일이 일어나고 있는지 아십니까? – netfreak

+0

@netfreak 나는하지 않지만, 잠깐 응시해서 그것이 나에게 도약하는지 알아볼 것이다. 나는 소켓 녀석이 아니지만이 사이트에는 많은 것들이있다. 그래서 아마도 하나가 소리를 질 것이다. – WhozCraig

2

(예 gdb ./a.out에 대한) 디버거에서 코드를 실행하고 시간에 알아 .

0

는 모르겠지만, 당신이 당신의 응답을 인쇄 할 때 C에서 문자열에 대한 널 (null) 종료는, '\ 0': "0"아 파크

recvdata[n] = 0; /* null terminate ----> this must be '\0'*/ 
if (fputs(recvdata, stdout) == EOF) 
err_sys("fputs error"); 

당신은 패드를, 따라서 fputs가 문자열을 구문 분석하여 인쇄하려면 segfault로 연결됩니다.

희망이 있습니다.

+0

ASCII에서, '\ 0'' =='0'. 하지만 명확하고 "\ 0"을 사용하면 아무런 해가 없습니다. – michaelb958

+0

알아두면 좋은 점! :) :) :) ty! – user2561272

관련 문제