現在、C言語でソケットライブラリやselectシステムコールを用いて複数人チャットのシステムを作っています。
チャットに参加するクライアントは以下のような構造体で管理しており、ソケットディスクリプタ・名前・チャットに送信するメッセージを保存しています。
c
1typedef struct{ 2 int sock; 3 char name[NAMELENGTH]; 4 char msg[MESSAGEMAXLENGTH]; 5} client_info; 6
そして以下のようにsendシステムコールやrecvシステムコール(自作ラッパー関数を使っています)を用いて、メッセージの送受信を行っています。
c
1// チャットサーバのメインループ 2void chat_loop() 3{ 4 int msg_sender_client; // メッセージを送信したclient_idを保存する 5 int client_id; 6 static char msgprompt[]="Input your message ↓: \n"; 7 8 9 for(;;){ 10 for(client_id=0; client_id<N_client; client_id++){ 11 Send(Client[client_id].sock, msgprompt, strlen(msgprompt), 0); 12 } 13 // メッセージを送信したclient_id受け取る 14 msg_sender_client = receive_message(); 15 16 // 送信されたメッセージとユーザ名を表示 17 send_message(msg_sender_client); 18 } 19} 20 21// クライアントからのメッセージを受信して、そのclient_idを返す 22static int receive_message() 23{ 24 fd_set mask, readfds; 25 int client_id, val; 26 int strsize; 27 28 /* ビットマスクの準備 */ 29 // クライアントのソケット番号 Client[client_id].sock を監視するように設定 30 FD_ZERO(&mask); 31 for(client_id=0; client_id<N_client; client_id++){ 32 FD_SET(Client[client_id].sock, &mask); 33 } 34 35 /* 受信データの有無をチェック */ 36 readfds = mask; 37 38 // データを送ってきたクライアントを知らべる 39 select( Max_sd+1, &readfds, NULL, NULL, NULL ); 40 41 for( client_id=0; client_id<N_client; client_id++ ){ 42 if( FD_ISSET(Client[client_id].sock, &readfds) ){ 43 // ユーザのメッセージをBufで受け取る 44 strsize = Recv(Client[client_id].sock , Buf, BUFLEN-1,0); 45 Buf[strsize]='\0'; 46 47 // Bufで受信したメッセージをユーザ構造体に保存する 48 if(strsize <= MESSAGEMAXLENGTH){ 49 strncpy(Client[client_id].msg, Buf, strsize); 50 }else{ 51 strncpy(Client[client_id].msg, Buf, MESSAGEMAXLENGTH); 52 } 53 val = client_id; 54 break; 55 } 56 } 57 return val; 58} 59 60// あるクライアントから送信されたメッセージをクライアント全員に送信する 61static void send_message( int msg_sender_client ) 62{ 63 int client_id; 64 char *msg = chop_nl(Client[msg_sender_client].msg); 65 int len; 66 67 // ユーザごとにメッセージの色を変える 68 switch (msg_sender_client) { 69 case 0: 70 len = snprintf(Buf, BUFLEN, "\x1b[34m <message from Mr.%s> %s \033[m\n", 71 Client[msg_sender_client].name, msg); 72 break; 73 case 1: 74 len = snprintf(Buf, BUFLEN, "\x1b[35m <message from Mr.%s> %s \033[m\x1b[0m\n", 75 Client[msg_sender_client].name, msg); 76 break; 77 case 2: 78 len = snprintf(Buf, BUFLEN, "\x1b[36m <message from Mr.%s> %s \033[m\x1b[0m\n", 79 Client[msg_sender_client].name, msg); 80 break; 81 default: 82 len = snprintf(Buf, BUFLEN, "\x1b[36m <message from Mr.%s> %s \033[m\x1b[0m\n", 83 Client[msg_sender_client].name, msg); 84 break; 85 } 86 87 // メッセージを送信 88 for(client_id=0; client_id<N_client; client_id++){ 89 Send(Client[client_id].sock, Buf, len,0); 90 } 91 92 // 今回以前のユーザ構造体のメッセージは初期化しておく 93 // TODO:初期化できてないみたい 94 memset(Client[msg_sender_client].msg, '\0', sizeof(Client[msg_sender_client].msg)); 95// Client[msg_sender_client].msg = ""; 96} 97 98// 文字列の改行を取り除く 99static char *chop_nl(char *s) 100{ 101 int len; 102 len = strlen(s); 103 if( s[len-1] == '\n' ){ 104 s[len-1] = '\0'; 105 } 106 return(s); 107} 108 109
static void send_message( int msg_sender_client )
内でメッセージの送信を行った後は、 memset(Client[msg_sender_client].msg, '\0', sizeof(Client[msg_sender_client].msg));
としてユーザのメッセージを初期化しているのですが、どうやらそれがうまく行っておらず、実行時に長めのメッセージの送信を行うとその後にそのメッセージのキャッシュ??が残ってしまいます。
どうすればメッセージを初期化することができるのかわからないため、教えていただきたいです。
よろしくお願い致します。