6

C でネットワーク プログラミングを学び始めたばかりです。いくつかのテストを行いましたが、エラーが発生しました。

クライアントがいます:

client.c

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

int main(void)
{
    struct addrinfo hints, *res;
    int sock;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    getaddrinfo("localhost", "5996", &hints, &res);
    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    connect(sock, res->ai_addr, res->ai_addrlen);
    char data[64];
    int len = 13;
    int br = recv(sock, data, len, 0);
    printf("%s\n%s\n%d\n", strerror(errno), data, br);
    return 0;
}

およびサーバー:

server.c

#include <string.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MYPORT "5996"
#define BACKLOG 10

int main(void)
{
    struct sockaddr_storage their_addr;
    socklen_t addr_size;
    struct addrinfo hints, *res;
    int sockfd, new_fd;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    getaddrinfo(NULL, MYPORT, &hints, &res);

    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    bind(sockfd, res->ai_addr, res->ai_addrlen);
    listen(sockfd, BACKLOG);

    addr_size = sizeof their_addr;
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);
    char *msg = "Hello World!!";
    int len = strlen(msg);
    int bs = send(new_fd, msg, len, 0);
    close(sockfd);
}

サーバーを起動すると、接続を待ちます。クライアントを起動すると、「Hello World !!」というメッセージが表示されますが、サーバーを実行してからクライアントを実行しようとすると、1 分ほどかかります。繰り返しますが、 strerror()呼び出しから「トランスポート エンドポイントが接続されていません」というメッセージが表示されます。

これに関する他の質問を読みましたが、問題は、accept()呼び出しから返されたソケットにデータを送信する必要があることでした...しかし、それが私がしていることだと思います。私は何を間違っていますか?? ...私はそれがばかげていることを知っていますが、私は本当の初心者です。

4

1 に答える 1

6

毎回同じポートでサーバーを再起動すると、そのポートがまだ OS によって使用されているものとして扱われることがあります。これは、最後のサーバー実行からのクライアントへの進行中のリクエストの配信に時間を割けるようにするためです。

setsockoptオペコードを呼び出すことでこれをオーバーライドできますSO_REUSEADDR

sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
int reuse = 1;
int err = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
if (0 == err)
    err = bind(sockfd, res->ai_addr, res->ai_addrlen);

上記のスニペットでは、エラーが返されるかどうかを確認していることに注意してください。各呼び出しのリターン コードをチェックしていれば、ここで問題 (解決策ではないにしても) を自分で発見できたはずです。

于 2013-02-12T12:04:47.363 に答える