2014-05-24 2 views
0

그래서 나는 배우려고하는 Beej의 가이드를 다음 봤는데 몇 가지 기본적인 http://beej.us/guide/bgnet/C 소켓 프로그래밍의 Recv가 send와 함께 정지됩니까?

그래서 나는 간단하게 만들려고 노력 해요 그래서 어떤하여 연습을 위해 작성된 코드의 일부 놀러하기로 결정 networking- 입력 IP 주소가 사용자가 연결할 수있는 터미널 대화방입니다. 문제는 내가 편집 한이 "서버"파일에서 정보를 전송할 때 잘 작동하지만 recv 함수 호출은 터미널을 고정시킵니다. 웬일인지. 그리고 나는 이유를 정말로 모르고있다. accept가 제대로 작동하면 new_fd 소켓을 사용하여 클라이언트의 소켓을 나타내는 것처럼 보내고받을 수 있다고 가정합니다 ... 이것은 내가 갇혀있는 곳입니다.

더 많은 실제적인 네트워킹 경험을 얻기 위해 내가 배워야 할 다른 라이브러리가 무엇인지 궁금합니다. 내 발이 정말 낮은 수준의 물건으로 젖어있는 좋은 방법이라고 생각합니다. (꽤 깊기 때문에 좋아해요.) C 네트워킹 라이브러리가 다른 것들과 비교할 때 특히 효과적이라고 생각하지 않습니다. "동결"there-

int waiting = 1; 
char input = ' '; 
char message[100]; 
memset(&message, 0, sizeof message); 

while(waiting) { // main accept() loop 
    sin_size = sizeof their_addr; 
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); 
    if (new_fd == -1) { 
     perror("accept"); 
     continue; 
    } 

    inet_ntop(their_addr.ss_family, 
     get_in_addr((struct sockaddr *)&their_addr), 
     s, sizeof s);//converts an IP address we get signal from to readable string 
    printf("%s wants to chat with you.\nAccept? Y/n\n", s); 
    scanf("%c", &input); 


    if (input == 'Y' || input == 'y') { 

     int rv; 

     /*if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { 
      close(sockfd); 
      perror("client: connect"); 
      continue; 
     }*/ 

     waiting = 0; 
    } 
    else { 
     printf("Waiting Mode\n"); 

    } 
} 

char buf[100]; 
char prev[100]; 
char nil[100]; 
memset(nil, 0, sizeof nil); 
int numbytes; 

while (1) { 

     fgets(message, 100, stdin); 


     if (send(new_fd, message, 100, 0) == -1) { 
      perror("send"); 
     } 


     if ((numbytes = recv(new_fd, buf, 100, 0)) == -1) { 
      perror("recv"); 
      exit(1); 
     } 

     /*if (strcmp(prev, buf) == 0 || strcmp(nil, buf) == 0) { 
      continue; 
     } 

     buf[numbytes] = '\0'; 
     printf("\n%s\n", buf); 
     memmove(prev, buf, sizeof buf);*/ 


} 

return 0; 

} 코멘트에 위에서 언급 한 바와 같이

+3

기본적으로 'recv'는 수신 할 데이터가있을 때까지 차단됩니다. –

+0

이 코드는 사용자가 채팅을 수락하지 않기로 선택하면 'new_fd'도 닫지 않습니다. 대기 루프가 종료되고 읽기가 시작될 때까지 유출 연결이있을 수 있습니다. –

답변

2

, 터미널은 recv에 차단 전화 때문이다. 대화방의 다른 구성원이 추가 정보를 보내지 않는 한, 프로그램은 거기에 앉아서 영원히 기다립니다. 언급 한 가이드는 네트워크 프로그래밍에 대한 훌륭한 참고 자료입니다. 돌아가서 특히 블로킹과 특히 cheezy-chat-room 예제에서 select()를 사용하면 7.1 절과 7.2 절을 다시 읽으십시오. 이것들은 예제가 멈추지 않고 작동하도록합니다. 당신이 select(), pselect()poll()에 익숙하지 않은 경우

, 좌절하지 않는, 그들은 친구를 만들기 위해 C의 가장 중요한,하지만 가장 어려운 측면 중 일부입니다. 잠시 시간을내어 가이드의 섹션 7.1 및 7.2를 검토하고 select()를 이해하면 시간 문제를 해결할 수 있습니다. select(), pselect()poll()은 네트워킹의 유용성에 제한이 없으며 프로그램 IO의 모든 측면에서 중요합니다.

+0

좋아요, 선택 섹션을 통해 읽으면서, 나는 그것을 이해합니다. 그러나 개념적으로 이해하고 싶습니다. - – Skorpius

+0

섹션을 통해 읽으므로, 이해할 것 같지만 확실하다고 확신합니다. 파일 디스크립터에는 "읽을 준비가되었습니다.", "쓸 준비가되었습니다", "현재 예외를 가지고 있습니다." FD_SET을 사용할 때 파일 디스크립터와 읽기, 쓰기 및 예외 세트에 대해 select는 해당 파일에 대해 현재 true로 설정된 특성을 알려줍니다. 소켓 설명자는보다 구체적인 파일 디스크립터이므로 이러한 특성을 상속 받습니까? 그가 STDIN을 0으로 사용했을 때, 0은 디폴트 C 값 이었습니까? 아니면 그가 임의로 선택한 값입니까? – Skorpius

+0

그것은 선택의 목적과 마법입니다. FD_SET은 select에 의해 감시 된 집합에 파일 기술자를 추가한다. FD_ISSET은 주어진 파일 설명자에서 읽을 수있는 경우 데이터를 반환합니다. '소켓 파일 디스크립터'는 '파일 디스크립터'와 비교해도 별 도움이되지 않는다. 리눅스 다. 모든 것이 파일이다. –