2009-05-20 2 views
6

아래 예제 코드는 서버 프로세스로 작동합니다. 잘못된 인수 - 나는C 소켓이 오류 코드 22를 발생시킵니다. EINVAL - 유효하지 않은 인수

struct sockaddr_in servaddr, clientaddr; 

아래 라인

pid_t childpid; 

를 추가 할 때이 오류 코드 (22), EINVAL과 일치

connectfd = accept(listenfd, (struct sockaddr *) &clientaddr, &clientaddrlen); 

에 실패합니다. C에서 소켓에 익숙하지 않아서 문제를 이해할 수 없었습니다.이 문제에 대해 저를 도와 줄 수 있습니까?

감사합니다.

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <linux/in.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 

extern int errno; 

int main() 
{ 
    int clientaddrlen, listenfd, connectfd, bytes_rcvd, listen_queue_size=1; 
    short int port_no = 2000; 
    char buffer[1000]; 
    struct sockaddr_in servaddr, clientaddr; 

    printf("Server running at port #%d\n", port_no); 

    // Create server socket. 
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
     fprintf(stderr, "Cannot create server socket! errno=%d \n", errno); 
     exit(-1); 
    } 
    printf("Server socket created\n"); 

    // Bind (attach) this process to the server socket. 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(port_no); 
    bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 
    printf("Server socket is bound to port #%d\n", port_no); 

    // Turn 'listenfd' to a listening socket. Listen queue size is 1. 
    listen(listenfd,listen_queue_size); 
    printf("Server listening with a queue of size %d. \n", listen_queue_size); 

    // Wait for connection(s) from client(s). 
    while (1) 
    { 
     connectfd = accept(listenfd, (struct sockaddr *) &clientaddr, &clientaddrlen); 
     printf("A client has connected\n"); 
     if (recv(connectfd, buffer, sizeof(buffer), 0) > 0) 
      printf("Received message: %s\n", buffer); 
     close(connectfd); 
     printf("Server closed connection to client\n"); 
    } 

    close(listenfd); 
    return 0; 
} 
+3

어? 사용되지 않는 변수 선언을 추가하기 만하면 프로그램의 동작이 변경됩니까? 그럴 것 같지 않은데, 틀린 선을 붙여 넣었 니? – unwind

+1

또한이 코드에서는 ... –

+0

에도 불구하고 fork()를 사용하지 않습니다. 실제로 이러한 동작은 매우 일반적입니다. 스택 프레임의 크기가 변경되어 버퍼 오버런 등으로 인한 문제가 노출되거나 숨겨 질 수 있습니다. –

답변

11

clientaddrlen의 초기화 위치가 표시되지 않습니다. 이것은 in/out 매개 변수입니다. accept() 주소의 버퍼 크기를 알려 주어야합니다.

+0

줄 추가 "clientaddrlen = sizeof ((struct sockaddr *) & clientaddr);" 트릭을 했어. 감사! – emrekyv

4

일반적으로 사용되지 않는 변수 선언을 추가하면 accept가 실패하지 않습니다. Select is not broken.

게시 한 코드는 설명대로 작동 할 수 없습니다. 당신은 accept()의 반환 값을 검사하지 않으므로 어떻게 실패하는지 알 수 있습니까? 유닉스 시스템/libc는 일반적으로 을 호출하는데 에러가 발생하지 않는 한 errno를으로 설정하지 않으므로 accept()가 -1을 반환하지 않으면 errno에을 포함 할 수 있습니다.

그건 그렇고; accept()가 실패하고 errno가 EINVAL로 설정 되었다면, 맨 페이지에 따라 두 가지 가능성이 있습니다 :

  • 소켓이 연결을 수신하지 않습니다.
  • Addrlen가 유효하지 않은 (즉, 음수)

EDIT (? 당신은 듣고()의 반환 코드를 확인 했) : 가장 중요한 : 를 컴파일하고 문제를 보여주는 전체 예를 게시 할 수 있습니다. 그렇지 않으면 문제가 무엇인지 추측 할 수 있습니다.

+0

나는 내가 작성한 다른 코드로 errno를 검사했다.이 간단한 버전이다. 잘못된 정보에 대해 사과드립니다. listen()은 0을 반환하므로 괜찮습니다. 그러나 clientaddrlen은 부정적입니다. 그 원인은 무엇일까요? – emrekyv

+0

지시문을 보내 주셔서 감사합니다. accept()의 맨 페이지를 확인한 결과 addrlen 인수는 값 - 결과 인수입니다. addr이 가리키는 구조체의 크기를 처음에 포함해야하며 반환시 실제 반환 된 주소의 길이 (바이트). " clientaddrlen을 초기화하고 문제를 해결했습니다! 여전히 변수 선언으로 인해 accept()가 실패하는 이유를 모르겠습니다. 나는 버그를 기대하지 않지만 어쨌든 왜 실패 하는지를 알고 싶다. 감사! – emrekyv

+0

@Neil이 주석을 달았으므로 변수를 추가하면 스택 레이아웃이 clientaddrlen으로 변경되어 실제로 음수가 아닌 값으로 초기화되고 accept()에 의해 받아 들여집니다. 그럼에도 불구하고 그것은 쓰레기 다. – JesperE

관련 문제