2016-05-15 21 views
3

私は、サーバーと通信してデータを送信および受信するクライアントコードを作成しています。 私は両方のファイルディスクリプタを監視するためにselect関数を使用しています - ソケットfdとしては、0をstdin fdとして、4(socket_dect)を監視します。 主なアイデアは、現時点でfdがアクティブであることを発見することです。もしSTDINGがアクティブであれば、ソケットfdがアクティブであればサーバーにデータを送信し、データを受信して​​印刷します。 私はこのクライアントを実行すると、理由は分かりませんが、嘆くことはありません。select()関数を使用してデータを送信および受信する

//チャットクライアント //スターター2に加えて、より問題についてはOMRI

#include <stdio.h> 
#include <sys/socket.h> 
#include <sys/select.h> 
#include <arpa/inet.h> //inet_addr 
#include <netinet/in.h> 
#include <string.h> 
#include <signal.h> 
#include <sys/time.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <errno.h> 
#include <fcntl.h> 


#define PORT 9034 // defined port like the server 
#define STDIN 0 

void main() 
{ 
    struct timeval tv; // time values for select function 
    int activity = 0 ; 
    int ready; // contains the result of the select function 
    char buf[256]; 
    int len = strlen(buf); 
    int byte_sent,i; 
    int socket_dect; // creating socket descriptor 
    struct sockaddr_in ServerInfo; 
    fd_set readfds; 

    // creating a new socket, its a number represent a file descriptor 
    // socket args : 1)ip protocol ipv4,second tcp/udp, third is number of protocol used 
    socket_dect = socket(AF_INET,SOCK_STREAM,0); 

    if(socket_dect == -1){ 
     perror("error creating socket"); 
    } 
    // fill the values of the server 
    ServerInfo.sin_family = AF_INET; // ipv4 
    ServerInfo.sin_port = htons(PORT); // port number 
    //ServerInfo.sin_addr = 127.0.0.1; 
    inet_pton(AF_INET, "127.0.0.1", &ServerInfo.sin_addr);//insert the ip to the sin addr 

    //fill the values of the time for the select function 
    tv.tv_sec = 5; // 5 sec 
    tv.tv_usec = 0; // 0 mili sec 
    FD_ZERO(&readfds); // clear the socket set 
    for(i = 0; i<= socket_dect; i++){ 
     FD_SET(i,&readfds);// set the sockets 
    } 

    // making the connection to the server 
    //ServerInfo.sin_addr.s_addr = inet_addr("127.0.0.1"); // another way to put ip addr 
    connect(socket_dect,(struct sockaddr *)&ServerInfo,sizeof(ServerInfo)); // connected to the server 
    printf("after connect"); 
    while(1){ 
     ready = select(socket_dect,&readfds,NULL,NULL,&tv); 
     printf("%d is ready",ready); 
     if(ready < 0){ 
      perror("select error"); 
      printf("select error"); 
     } 
     // reading from STDIN to buff 
     else if(ready == STDIN_FILENO){ 
      if(fread(buf,256,1,&readfds) < 0){ 
       printf("read error"); 
       perror("read error"); 
      } 
      if(send(socket_dect,buf,len,NULL) < 0){ 
       perror("send connection"); 
       printf("send error"); 
      }//end if send 
     }//end elseif STDIN 
     else if(ready == socket_dect){ 
      if(recv(socket_dect,buf,len,0) < 0){ 
       printf("recv error"); 
      } 
      printf("data recived is :%s",buf); 
     }//end elseif 
     else{ 
      printf("none is ready"); 
     } 
    }//end while 
}//end main 
+0

[manページの選択](http://linux.die.net/man/2/select)から:「nfdsは、3つのセットのうち、最も高い番号のファイル記述子です** ** 1 ** " – kaylum

+1

'if(ready == STDIN_FILENO)'であり、どのファイル記述子が準備完了であるかを確認する正しい方法ではありません。再度、マニュアルページを参照してください。「終了時に、セットは実際にどのファイル記述子がステータスを変更したかを示すために変更されます。 – kaylum

+3

'select'は渡されたfdセットを変更するので、fdセット、この場合は' readfds'をループの繰り返しごとに再設定する必要があります。また、セットはそれらの値の間のすべてのファイル記述子の代わりに 'STDIN_FILENO'と' socket_dect'だけを含むべきです。 – kaylum

答えて

3

によって書かれた: が、これは私のコードです。

nfds個 3セットのいずれか、プラス1で最も高い番号のファイルディスクリプタである:

はこの

ready = select(socket_dect,&readfds,NULL,NULL,&tv); 

ready = select(socket_dect + 1, &readfds, NULL, NULL, &tv); 

man selectからでなければなりません。


代わりの

if(ready == STDIN_FILENO) 

使用

if (FD_ISET(STDIN_FILENO, &readfds) 

select()はあなたが再初期化彼らにselect()を呼び出す前に、すべての時間を必要とするので、それが内部にあり、渡されたパラメータを変更しますループ。

また

あなたはすべてのシステムがその成果を求め必見テスト。これにはconnect()が含まれます。

また

^2それは(ここではlen)に言われたとして、あなたは多くのバイトとしてrecv()リターンを前提としない場合があります。受け取った人はほとんどいないことがあります。あなたが望んでいるほど多くを得ていることを確認するには、周りにループrecv()を回してください。

関連する問題