2010-12-06 87 views
0

我刚开始学习网络编程。我的第一个程序非常简单:连接后,服务器程序显示客户端程序发送的内容(字符)。一切正常,直到他们连接。起初,我没有使用putc将发送循环:简单的网络编程程序 - 不工作

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

和接收一个与GETC:

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。这是什么意思?我在哪里做错了?顺便说一句,我使用Linux和gcc。

非常感谢您的帮助! :)


编辑:即使我使用的getc()和putc(),我与插座(连接),然后我连接()(客户端)。服务器在获得连接(使用socket())bind()s后,listen()s和accept()s。对不起,如果我ometted。


这里的服务器代码:

#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); 
} 

和客户端的代码:

#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); 
    } 
} 

在结束...

它完美!感谢大家。 :)

+0

如何使用期望文件句柄的函数进行网络编程? '连接'的价值是什么?基本上,你应该使用'套接字/发送/接收'。 – KevinDTimm 2010-12-06 18:42:56

+0

Linux上的107是“ENOTCONN”。代码'getc((FILE *)connection))'看起来很可疑:'连接'的类型是什么? – vanza 2010-12-06 18:44:07

+0

int。用socket()获得。 – BlackBear 2010-12-06 18:50:32

回答

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 2010-12-06 18:49:51

+0

我做了,但无论如何它都无法工作。 – BlackBear 2010-12-06 18:57:49

1

当您使用铸件(如(FILE *) connection)你告诉编译器:“相信我,这是真理”。当你对编译器说谎时,它相信你。

你已经对编译器撒谎了。 connection不是指向FILE结构的指针。分段错误是你可以得到的最好结果,因为它告诉你一些错误。

1

你做一些编程错误:

1)memset的(STR,空,strlen的(memset的));

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

2),而(((C = GETC(标准输入))!= '\ 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);