2010-03-03 5 views
0

기본적으로 서버를 설정하고 새로운 클라이언트 (UNIX)를 받아들이고 select() 명령을 사용하여 파일 설명자의 작업을 기다리고 있지만 어떻게 작동하는지 기다리고 있습니다. 서버 측소켓을 사용하여 클라이언트 측에서 읽기

FD_ZERO(&readfds); 
FD_SET(server_sockfd, &readfds); 
FD_SET(STDIN_FILENO, &readfds); 
while (1) { 
    testfds = readfds; 
    select(4 + MAXCLIENTS, &testfds, NULL, NULL, NULL); 
    for (fd = 0; fd < 4 + MAX_CLIENTS; fd++) { 
    if (FD_ISSET(fd, &testfds)) { 
     if (fd == server_sockfd) { /* new connection request */ 
      client_sockfd = accept(server_sockfd, NULL, NULL); 
      if (num_clients < MAXCLIENTS) { 
       FD_SET(client_sockfd, &readfds); 
       num_clients++; 
      } else { 
       sprintf(message, "XSorry, too many clients. Try again later.\n"); 
       write(client_sockfd, message, strlen(message)); 
       close(client_sockfd); 
      } 
     } else if (fd == STDIN_FILENO) { 
      fgets(kb_message, BUFSIZ + 1, stdin); 
      if (strcmp(kb_message, "quit\n") == 0) { 
       sprintf(message, "XServer is shutting down.\n"); 
       for (fd2 = 4; fd2 < 4 + MAX_CLIENTS; fd2++) { 
       if (FD_ISSET(fd2, &readfds)) { 
        write(fd2, message, strlen(message)); 
        close(fd2); 
       } 
       } 
       close(server_sockfd); 
       exit(EXIT_SUCCESS); 
      } else { 
       sprintf(message, "M%s", kb_message); 
       for (fd2 = 4; fd2 < 4 + MAX_CLIENTS; fd2++) 
       if (FD_ISSET(fd2, &readfds)) 
        write(fd2, message, strlen(message)); 
      } 
     } else { /* client leaving */ 
      close(fd); 
      FD_CLR(fd, &readfds); 
      num_clients--; 
     } 
    } 
    } 

}에 그것을 읽고 다음 클라이언트 측에서 작성하는

는 "다른"방법에 따라 될 것 어떻게, 클라이언트로부터의 쓰기 요청을 처리 한 후 다시 그들에게 작성합니다 클라이언트가 종료 또는 작성 중인지 확인할 수 있습니까?

감사

+0

@Roberto : 코드를 다시 편집하고 싶을 수도 있습니다. –

답변

1

'else'블록에 읽기 코드가 필요하다고 생각하는 것이 맞습니다. 파일 디스크립터가 시작되어 'stdin'또는 'connect'디스크립터가 아닌 경우, 이는 클라이언트에게 데이터를 보내려고 시도하는 것이다. 해당 파일 디스크립터 중 하나가 select에서 트리거되면 해당 디스크립터에서 'read'를 호출하여 데이터를 버퍼로 읽어야합니다. read 명령은 읽은 바이트 수를 반환합니다. 이것이 양수이면 클라이언트가 데이터를 보낸 것을 나타냅니다. 0이면 클라이언트가 서버에 대한 TCP 연결을 종료했음을 나타냅니다.

다른 블록과 같이 보일 것이다 : 또한

else 
    { 
    //Existing connection has data for us to read 
    if((nBytes = read(fd, buffer, MAXBUFFER)) <= 0) 
    { 
     if(nBytes == 0) 
     { 
      //Actually, its sending us zero bytes, connection closed 
      printf("Socket %d hung up\n", fd; 
     } 
    else 
      printf ("Read Error"\n) 
    } 

을 위 니콜라이 N Fetissov의 조언에 따라 고객의 당신이 하나로 사용하고, 영구적 인 FD_SET 구조에서 자신의 FD를 저장 연결할 때 있는지 확인 선택 호출에 의해 수정 중입니다.

+0

위의 코드를 사용해 보겠습니다. 감사합니다. – Roberto

0

귀하의 문제는 당신이 read라는 변수를 가지고있을 수 있습니다. 그것은 소켓에서 데이터를 가져 오기위한 read() 시스템 호출을 사용해야하는 hte 함수 중 하나를 감추고 있습니다. 클라이언트는 write()을 입력합니다. 반환 값을 select()에서 확인할 수도 있습니다. 그러면 파일 설명자를 몇 개나 읽을 준비가되었는지 알 수 있습니다. 그런 다음 어떤 것을 FD_ISSET()을 사용하여 확인할 수 있습니다. 그것은 당신이 이미 그 부분을하고있는 것처럼 보입니다. (틀린 변수를 체크하는 것만 빼면?) ... 그 파일 기술자에 read()을 호출하면 클라이언트가 작성한 데이터를 얻을 수 있습니다.

+0

이것은 아마도 오타 일 뿐이며, 'select (2)'다음에 루프에서'readfds'를 실행하십시오. –

+0

@ 니콜라이, 맞습니다. 'StDIN_FILENO'에 이상한 케이스가 있습니다. 나는 이것이 실제 코드가 아닌 것 같아요. –

2

select(2) 가장 일반적인 실수는 하지 재 초기화 설명하는 두 번째, 세 번째 이후을 설정하고, 항 인자 입출력 파라미터이다.

fd_set이, 외부 루프 전에 읽기 위해, 그것에 소켓 설명을 듣고 추가 설정, 루프를 입력 는이 fd_set의 사본을하고 select(2)에 복사본을 제공합니다. 새 연결이 도착하면 원래fd_set에 설명자를 추가하십시오. 닫힌 소켓 (오류 또는 EOF가 read(2) 인 경우) - 원래fd_set에서 설명자를 제거하십시오.

희망이 도움이됩니다.

0
else 
{ 
    bzero(buf,100); 
    n=read(i,buf,100); // Read the client message 
      buf[n]='\0'; 
     if(n==0) // Check the client is closed or not 
     { 

       printf("%d is closed\n",i); 
       close(i); 
       FD_CLR(i, &master); 
       if(i==fdmax) 
       fdmax--; 

     } 
     else 
     { 
      n=strlen(buf); 

     write(1,buf,n); 
     fflush(stdout); 

      write(1,"Enter the message\n",18); 
      bzero(buf,100); 
      read(0,buf,100); 
      buf[n]='\0'; 
      write(i,buf,n); 
      fflush(stdout); 
     } 
    } 

참고 : 이 후, 클라이언트를 수락 FD 세트에 클라이언트를 추가합니다. 그런 다음 클라이언트에서 메시지를 읽습니다. 메시지가 0이면 클라이언트가 닫힙니다. 클라이언트 fd를 사용하여 클라이언트에 메시지를 보내려는 경우 클라이언트에게 보낼 수 있습니다.

관련 문제