2010-12-06 14 views
0

私はちょうどネットワークプログラミングを学び始めました。私の最初のプログラムはとてもシンプルです。一度接続すれば、サーバープログラムはクライアントプログラムが送信するもの(文字)を表示します。接続されるまではすべて正常に動作します。最初は、私はPUTCを使用して送信するループをしました:シンプルなネットワークプログラミングプログラム - 動作しません

while((c = getc(stdin)) != '\n') 
    putc(c, (FILE *) connection); 

とgetc関数と受信1:

while((c = getc((FILE *) connection)) != '\n') 
    putc(c, stdout); 

接続したら、私はセグメンテーションフォールトを取得します。それから私は送って使用してみました:

while(1) { 
    memset(str, null, strlen(memset)); 

    while(((c = getc(stdin)) != '\n') && sizeof(str) <= 100) { 
     strcat(str, (char *) c);  // cast to char * is to make gcc happy 
    } 

    send(connection, (void *) str, sizeof(str), (int) NULL); 
} 

とのrecv:

while((stat = recv(connection,str,100,0)) != 0) { 
    printf("\nReceived %d bytes of data from %s: %s", stat, client, str); 
} 

は今のrecv()は、これが何を意味し-1を返すとerrnoが107に設定され続けますか?どこが間違っていますか?ところで、gccでLinuxを使用しています。

ありがとうございました! :)


編集:私はgetc関数()とPUTCを()を使用した場合でもは、私が(ソケットとの接続を取得)、その後、私は(コネクト)(クライアント)。サーバーは、接続(socket()で)bind()sを取得した後、listen()およびaccept()を呼び出した後に取得します。ごめんなさい、申し訳ありません。それは完璧に動作

...終わり

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <errno.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

void main(int argc, char *argv[]) 
{ 
    struct addrinfo hint; 
    struct addrinfo *servinfo, *count; 
    struct sockaddr_storage conn_addr; 
    struct sockaddr host; 

    int connessione; 
    int stat; 
    int conn_sock; 
    int conn_size; 
    int success; 
    int c; 

    char t[INET_ADDRSTRLEN]; 
    char *indirizzo; 
    char str[100]; 

    memset(&hint,0,sizeof hint); 

    host.sa_family = AF_INET; 
    if(inet_pton(host.sa_family, argv[1], (void *) host.sa_data) == -1) { 
     printf("\n[FATAL]: pton: %s (%d)\n", gai_strerror(errno), errno); 
     exit(-1); 
    } 

    hint.ai_family = AF_INET; 
    hint.ai_socktype = SOCK_STREAM; 
    hint.ai_flags = AI_PASSIVE; 
    hint.ai_addr = &host; 

    if((stat = getaddrinfo(argv[1], argv[2], &hint, &servinfo)) != 0) { 
     printf("[FATAL]: getaddrinfo: %s\n",gai_strerror(stat)); 
     exit(-1); 
    } 

    success = 0; 
    for(count = servinfo; count != NULL; count = count->ai_next) { 
     if((connessione = socket(count->ai_family, count->ai_socktype, count->ai_protocol)) == -1) 
      continue; 

     if(connect(connessione, count->ai_addr, count->ai_addrlen) != -1) { 
      success = 1; 
      break; 
     } 
    } 

    if(success == 0) { 
     printf("\n[FATAL]: impossibile trovare l'host specificato\n"); 
     exit(-1); 
    } 

    servinfo = count; 
    freeaddrinfo(count); 

    indirizzo = (char *) malloc(INET_ADDRSTRLEN * sizeof(char)); 
    indirizzo = inet_ntop(servinfo->ai_family, &conn_addr, t, INET_ADDRSTRLEN); 

    printf("\n[DEBUG]: %s: connesso a: %s\n",argv[0], indirizzo); 

    while(1) { 
     strcpy(str,"buffer for data to send"); 

     while(((c = getc(stdin)) != '\n') && sizeof(str) <= 100) { 
      strcat(str, (char *) c); 
     } 

     send(connessione, (void *) str, sizeof(str), (int) NULL); 
    } 
} 

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <errno.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

void main(int argc, char *argv[]) 
{ 
    struct addrinfo hint; 
    struct addrinfo *servinfo, *count; 
    struct sockaddr_storage conn_addr; 
    struct sockaddr host; 

    int connessione; 
    int stat; 
    int conn_sock; 
    int conn_size; 
    int success; 
    int c; 

    char t[INET_ADDRSTRLEN]; 
    char str[100]; 
    char *client; 

    if(argc != 1 && strcmp(argv[1], "aiuto") == 0) { 
     printf("%s(porta)\n",argv[0]); 
     printf("porta: specifica su quale porta installarsi\n"); 
     exit(-1); 
    } 

    memset(&hint,0,sizeof hint); 


    hint.ai_family = AF_INET; 
    hint.ai_socktype = SOCK_STREAM; 
    hint.ai_flags = AI_PASSIVE; 

    if((stat = getaddrinfo(NULL, argv[1], &hint, &servinfo)) != 0) { 
     printf("\n[FATAL]: getaddrinfo: %s",gai_strerror(stat)); 
     exit(-1); 
    } 

    success = 0; 

    for(count = servinfo; count != NULL; count = count->ai_next) { 
     if((connessione = socket(count->ai_family, count->ai_socktype, count->ai_protocol)) <= 0) 
      continue; 

     if((stat = bind(connessione, count->ai_addr, count->ai_addrlen)) == 0) { 
      success = 1; 
      break; 
     } 
     else { 
      continue; 
     } 
    } 

    if(success == 0) { 
     printf("\n[FATAL]: Unable to bind()!\n"); 
     exit(-1); 
    } 
    else { 
     printf("\n[DEBUG]: %s: listening...", argv[0]); 
    } 

    servinfo = count; 
    freeaddrinfo(count); 

    if(listen(connessione, 20) == -1) { 
     printf("\n[FATAL]: listen: %s (%d)\n", gai_strerror(errno), errno); 
     close(connessione); 
     exit(-1); 
    } 

    conn_size = sizeof(conn_addr); 

    if(accept(connessione, (struct sockaddr *) &conn_addr, &conn_size) == -1) { 
     printf("\n[FATAL]: accept: %s", gai_strerror(errno)); 
     close(connessione); 
     exit(-1); 
    } 

    client = (char *) malloc(INET_ADDRSTRLEN * sizeof(char)); 
    client = inet_ntop(servinfo->ai_family, &conn_addr, t, INET_ADDRSTRLEN); 

    printf("\n[DEBUG]: %s: connection accepted: %s", argv[0], client); 

    while((stat = recv(connessione,str,100,0)) != 0) { 
     printf("\nReceived %d bytes of data from %s: %s", stat,client, str); 
    } 

    printf("\n[DEBUG]: connection closed by %s\n",client); 
} 

、クライアントのコード:


はここでサーバーのコードです!みんな、ありがとう。 :)

+0

ファイルハンドルが必要な機能でネットワークプログラミングを行うにはどうすればよいですか? 「接続」の価値は何ですか?本質的に、あなたは 'socket/send/recv'を使うべきです。 Linuxの – KevinDTimm

+0

107は "ENOTCONN"です。コード 'getc((FILE *)connection))'は疑わしいと思われます。「接続」のタイプは何ですか? – vanza

+0

int。 socket()で得られます。 – BlackBear

答えて

5

通常、ネットワークプログラミングを行うにはFILE *ハンドルを使用しません。むしろ、socket(2)システムコールによって返されたソケット記述子が必要です。一度それを持っていれば、それはconnect(2)(クライアント)かbind(2)(サーバー)のいずれかです。進行中の通信は、recv(2)およびsend(2)を使用して実行できます。

実際にFILE *ハンドルを使用してネットワークプログラミングを行う場合は、fdopen(3)ライブラリ機能をご覧ください。 socket(2)によって返される可能性のあるディスクリプタをとり、fread/fwrite/fprintfと互換性のあるハンドルFILE *を返します。

if (accept(connessione, (struct sockaddr *) &conn_addr, &conn_size))

accept(2)はあなたがrecv(2)/send(2)を使用する必要がソケットを返し、あなたが使用して、それを捨てる:

あなたの完全なコードを掲示した後、私が見ることができる最も重要なエラーが発生しました代わりにサーバーソケット。

+0

私の編集を見てください。私はそれを忘れてしまった。 – BlackBear

+0

私はしましたが、とにかく動作しません。 – BlackBear

+0

初期化の呼び出しを含むコードを投稿すると、何かを見つけるのに役立ちます。 –

1

私はあなたがコンパイラを言っている。これは、あなたが((FILE *) connectionのような)キャストを使用する場合

+0

私はそれについてすぐに研究しました! =) – BlackBear

+0

あなたはそれをどこから取得しましたか:putc(c、(FILE *)connection); – Incubbus

+0

それは私のものです。私はキャラクターを一度送ろうと思ったのでそれを試しました、それは私にはもっと見えました。 – BlackBear

1

をプログラミングソケットに非常に素晴らしいガイドであるあなたがhttp://beej.us/guide/

を読んでお勧め:「私を信じて、これは真実であります"あなたがコンパイラに嘘をつくとき、それはあなたを信じます。

あなたはコンパイラに嘘をついています。 connectionは、FILE構造体へのポインタではありません。セグメンテーションフォールトは、あなたが得ることができる最も良い結果です。なぜなら、何かが間違っていることを伝えるからです。

+0

これは意味があります。ありがとう。 +1 – BlackBear

1

あなたは、いくつかのプログラミングエラーを行います

1)のmemset(STR、ヌル、strlenを(memsetの));

should be : memset(str ,0 ,sizeof(str)); // if str is declared as char str[100]; 

2)一方、(((C = GETC(STDIN))!= 'の\ n')& &はsizeof(STR)< = 100)

shhould be : while(((c = getc(stdin)) != '\n') && (strlen(str) <= 100)) 

3)送信(接続、 (void *)str、sizeof(str)、(int)NULL);

should be : send(connection, (void *) str, strlen(str), (int) NULL); 
+0

ありがとうございます。私は修正します。 =) – BlackBear

関連する問題