简单的网络编程程序 - 不起作用

发布于 2024-10-06 04:14:44 字数 5856 浏览 3 评论 0原文

我刚刚开始学习网络编程。我的第一个程序非常简单:连接后,服务器程序显示客户端程序发送的内容(字符)。在连接之前一切正常。首先,我使用 putc: 进行发送循环,

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

并使用 getc: 进行接收循环:

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

一旦连接,就会出现分段错误。然后我尝试使用send:

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() 建立连接,然后我 connect() (客户端)。服务器在获得连接(使用socket())后bind()s,然后是listen()s和​​accept()s。抱歉,如果我遇见了。


这是服务器代码:

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

最后...

它工作得很好!谢谢大家。 :)

I just began learning network programming. My first program is very simple: once connected, the server program displays what the client program sends (characters). Everything works fine until they get connected. At first, I did the sending loop using putc:

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

and the receiving one with getc:

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

Once connected, I get a segmentation fault. Then I tried using send:

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

and recv:

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

Now recv() keeps returning -1 and errno is set to 107. What does this mean? Where am I doing wrong? By the way I'm using Linux with gcc.

Thanks a lot for your help! :)


EDIT: Even if I used getc() and putc(), I get connection with socket(), then I connect() (client). The server, after obtaining connection (with socket()) bind()s, then listen()s and accept()s. Sorry if I ometted.


Here's the server code:

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

And the client's code:

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

At the end...

It works perfectly! Thanks everyone. :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

饮惑 2024-10-13 04:14:44

通常,您不使用 FILE * 句柄进行网络编程。相反,您需要一个由 socket(2) 系统调用返回的套接字描述符。获得它后,您可以connect(2)它(客户端)或bind(2)它(服务器)。可以使用 recv(2)send(2) 执行正在进行的通信。

如果您确实想使用FILE *句柄进行网络编程,请查看fdopen(3)库函数。它接受一个可以由 socket(2) 返回的描述符,并返回一个与 fread / fwrite 兼容的 FILE * 句柄 / fprintf

发布完整代码后,我看到的最重要的错误是:

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

accept(2) 返回一个必须与 recv(2) / send(2) 一起使用的套接字,然后将其丢弃,改用服务器套接字。

Normally you don't use a FILE * handle to do network programming. Rather, you need a socket descriptor returned by the socket(2) system call. Once you have it, you can either connect(2) it (the client) or bind(2) it (the server). The ongoing communication can be performed using recv(2) and send(2).

If you really want to use a FILE * handle to do network programming, take a look at the fdopen(3) library function. It takes a descriptor that could be returned by socket(2) and returns a FILE * handle that is compatible with fread / fwrite / fprintf.

After posting your full code, the most significant error that I could see was:

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

accept(2) returns a socket which you have to use with recv(2) / send(2), and you discard it, using the server socket instead.

清风疏影 2024-10-13 04:14:44

我建议您阅读 http://beej.us/guide/

这是一本非常好的套接字编程指南

I suggest You reading http://beej.us/guide/

This is a very nice guide to socket programming

も让我眼熟你 2024-10-13 04:14:44

当您使用强制转换(如 (FILE *) 连接)时,您是在告诉编译器:“相信我,这是事实”。当你对编译器撒谎时,它会相信你。

你对编译器撒了谎。 connection 不是指向 FILE 结构的指针。分段错误是您可以获得的最好结果,因为它告诉您出现了严重错误。

When you use a cast (like (FILE *) connection) you're telling the compiler: "trust me, this is the truth". When you lie to the compiler it believes you.

You have lied to the compiler. connection is not a pointer to a FILE structure. A segmentation fault is the nicest result you can get, because it tells you something is badly wrong.

百变从容 2024-10-13 04:14:44

您犯了一些编程错误:

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

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

2) while(((c = getc(stdin)) != '\n') && sizeof(str) <= 100)

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

3) send(connection, (void *) str, sizeof(str), (整数)空);

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

You make some programming errors:

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

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

2) while(((c = getc(stdin)) != '\n') && sizeof(str) <= 100)

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

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

should be : send(connection, (void *) str, strlen(str), (int) NULL);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文