2016-10-31 2 views
1

소켓을 사용하여 C의 클라이언트/서버 명령 행 채팅 프로그램을 작성하고 있습니다. 한 가지 문제를 제외하고는 모든 것이 잘 작동하고 있습니다. 클라이언트가 서버에 잘못된 명령을 제출하면 명령 목록을 다시 보내 응용 프로그램 사용 방법을 알려줍니다. 나는 여러 개의 연속적인 "보내기"를 수행하여이 작업을 시도했지만 클라이언트는 첫 번째 메시지 만 가져옵니다. 나는 (자바 소켓을위한) 비슷한 질문 몇 개를 찾았지만, 이것에 대한 답을 찾지 못했습니다.C - 소켓 채팅방 - 클라이언트가 연속 메시지 받기

코드 및 출력

서버 측 코드 : (별도의 스레드 루프)

void message_self(char *msg, client_t *client) { 
    send(client->sd, msg, strlen(msg) + 1, 0); 
} 

void commands(client_t *client) { 
    message_self("Commands:\n", client); 
    message_self("\tUser Login:\tlogin <username> <password\n", client); 
    message_self("\tCreate User:\tnewuser <username> <password>\n", client); 
    message_self("\tList Users:\twho\n", client); 
    message_self("\tMessaging:\tsend all|<username> <message>\n", client); 
    message_self("\tQuit Chat:\tlogout\n", client); 
} 

클라이언트 사이드 :

if((len = recv(sd, buff_in, sizeof(buff_in), 0)) > 0) { 
    fputs(buff_in, stdout); 
} 

출력 : 빈 줄은 사용자가 방금 입력 타격이다 그래서 서버는 명령 (클라이언트)을 호출합니다. 1 줄만 수신하면 사용자가 "send"를 입력하고 서버에서 해당 오류 메시지를 받았습니다. 난 그냥 더 나은 방법이있을 생각

Connected. Chat Room Version 2 

Commands: 
    User Login:  login <username> <password> 
    Create User: newuser <username> <password> 
    List Users:  who 
    Messaging:  send all|<username> <message> 
    Quit Chat:  logout 

: 다음 각 message_self 사이 (50) usleep 넣으면

Connected. Chat Room Version 2 

Commands: 
send 
Server: Denied. Please log in. 

내가 예상 출력을 얻을. 또한 전체 목록을 모든 서식 지정 문자가있는 하나의 버퍼로 연결하려고 시도했지만 "명령 :"을 인쇄 한 후에도 여전히 클라이언트 측에서 차단되었습니다. 누구든지 서버 측의 클라이언트 측에서이 문제를 해결하는 방법을 알고 있다면 감사하게 생각합니다.

+1

전송, 당신은 각 줄 끝에서 종료'\ 0''을 포함한다. 수신 측에서는 'fputs'는 첫 번째 '\ 0', 즉 단 한 줄만 인쇄합니다. 모든 라인이 하나의 패킷으로 전송되는 이유는 아마도 [Nagle의 알고리즘] (https://en.wikipedia.org/wiki/Nagle%27s_algorithm) 일 것입니다. 일반적으로 네트워크를 통해 수신 된 데이터의 null-termination에 의존해서는 안되며, 대신 데이터의 길이를 먼저 전송하십시오. –

+0

버퍼가 충분히 큰 경우 하나의 메시지로 전체 명령 목록을 보내는 것을 고려할 수 있습니다. –

+0

@KarstenKoop - 이것이 의미가 있습니다. 그렇다면 클라이언트 측에서 쉽게 분해 할 수 있습니다. – sylisphoenix

답변

0

@KarstenKoop이 주석을 달았으므로 서버에서 널 종결자를 보내면 모든 것이 망가집니다. 대신 strlen 바이트를 보내고 lput을 사용하여 클라이언트 측에서 fputs에 대한 메시지를 종료하십시오.

서버 :

send(client->sd, msg, strlen(msg), 0); 

클라이언트 :

if((len = recv(sd, buff_in, sizeof(buff_in), 0)) > 0) { 
    buff_in[len] = '\0'; 
    fputs(buff_in, stdout); 
} 
관련 문제