2011-08-13 6 views
1

これは私の最初の質問です。私はUnixのCソケットを学びたいと思っています。学習の一環として、指定されたポート上のホストに接続し、サーバーから受信した文字を出力し、ユーザーがコンソールに書き込んだものを送信する単純なTelnetライクなクライアントをコード化しようとしました。それはうまく受信しますが、文字列を送信しようとすると何も起こりません。次に、プログラムを中断すると、送信しようとしたすべての文字列が送信されます。ありがとうございました。私はたぶん馬鹿だ。CソケットSend()はプログラムが終了するまで送信しません。

#include <stdio.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <fcntl.h> 

int SetupSock(char *host, char *port) { 
    int s, status; 
    struct addrinfo hints, *res; 
    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    getaddrinfo(host, port, &hints, &res); 
    if((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) { 
     printf("Could not create sock...root?\n"); 
     exit(1); 
    } 
    if((status = connect(s, res->ai_addr, res->ai_addrlen)) == -1) { 
     printf("Connect Failed: %s\n", strerror(errno)); 
     printf("%s", strerror(errno)); 
     printf("\n");  
     exit(1); 
    } 
    return s; 
} 

int main (void) { 
    char *host = malloc(100), *port = malloc(20), buf[2], *msg = malloc(1000); 
    struct timeval waitid; 
    fd_set read_flags, write_flags; 
    signal(SIGPIPE, SIG_IGN); 
    int sock, flags; 
    //Input Host and Port 
    printf("Host: "); 
    gets(host); 
    printf("Port: "); 
    gets(port); 
    sock = SetupSock(host, port); 
    flags = fcntl(sock, F_GETFL, 0); 
    fcntl(sock, F_SETFL, flags | O_NONBLOCK); 
    FD_ZERO(&read_flags); 
    FD_ZERO(&write_flags); 
    FD_SET(sock, &read_flags); 
    FD_SET(fileno(stdin), &read_flags); 
    fflush(0); 
    int pid = fork(); 
    if (pid == 0) { 
     int status; 
     close(stdout); 
     while(1) { 
     select(sock + 1, &read_flags, &write_flags, (fd_set*) 0, &waitid); 
     if (FD_ISSET(fileno(stdin), &read_flags)) { 
      gets(msg); 
      if((status = send(sock, msg, strlen(msg), MSG_NOSIGNAL)) == -1) { 
       printf("Send Failed: %s\n", strerror(errno)); 
      } 
     } 
     } 
    } 
    else { 
     close(stdin); 
     while(1) { 
      select(sock + 1, &read_flags, &write_flags, (fd_set*) 0, &waitid); 
      if (FD_ISSET(sock, &read_flags)) { 
       if(recv(sock, &buf, 1, 0) > 0){  
        printf("%s", buf); 
       } 
      } 
     } 
    } 
    close(sock); 
    return 0; 
} 
+0

受信側を表示します。 – cnicutar

+0

2つの異なるプロセスを使用して送受信するのが奇妙に見えます。これを行うには、使用していないstdout/stdin fdを閉じる必要があります。 –

+0

@cnicutar:相手のために何かを使うことができます。私はOPがインターネットからランダムなhttpサーバを使用したと思いますが、これは問題ありません。問題はこのコードからです。 –

答えて

1

selectは、ここで1回だけ実行されます。それはループ内にあるはずです。 selectは、提供された一連のファイル記述子でイベントが発生するのを待機します。 各イベントが処理された後、再度呼び出される必要があります。

+0

'select'が実行された後、' fork'が起動し、プログラムは読み込みプロセスと書き込みプロセスに分割されます。だからその選択は役に立たない。より多くの 'select'sは何も追加しません。 – cnicutar

+0

@cnicutar:select wilによって返される 'sock'と' stdin'の状態は永遠に固定されます。それは、 'sock'がselectを単独でアンロックした(または' stdin'がロックを解除した)ことでしょう。これらの場合、 'gets'と' send'のうちの一つだけが実行されます。したがって、何かが変更されたかどうかを再度確認する必要があります。 –

+0

実際、私はFD_ISSETを 'gets'に気付かなかった。 – cnicutar

0

エリアをカバーするには、selectとstdio の両方を入力してください。を入力してください。バッファリングのためにfileno(stdin)が読み取り可能かどうかによって、stdinが読み取り可能かどうかの正確な結果を得ることはできません。

関連する問題