0

TCP クライアントと TCP サーバーを実装しようとしています。接続を確立することはできますが、クライアントからメッセージを送信すると、サーバーはそれを受信しません。以前の投稿を確認したところ、同様の問題がたくさんありました。私はそれらに従いましたが、それでも同じエラーが発生します。私が得ているエラーはサーバー側からのものです:

recv: Socket operation on non-socket

これが私のコードです。私が間違っていることを教えていただければ、本当に感謝しています。サーバーの実装に問題があると思います。

サーバ:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 3490
#define BACKLOG 10

int main()
{
    struct sockaddr_in server;
    struct sockaddr_in dest;
    int status,socket_fd, client_fd,num;
    socklen_t size;

    char buffer[10240];
    memset(buffer,0,sizeof(buffer));
    int yes = 1;

    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
        fprintf(stderr, "Socket failure!!\n");
        exit(1);
    }

    if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    memset(&server, 0, sizeof(server));
    memset(&dest,0,sizeof(dest));
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr.s_addr = INADDR_ANY; 
    if ((bind(socket_fd, (struct sockaddr *)&server, sizeof(struct sockaddr )))== -1)    { //sizeof(struct sockaddr) 
        fprintf(stderr, "Binding Failure\n");
        exit(1);
    }

    if ((listen(socket_fd, BACKLOG))== -1){
        fprintf(stderr, "Listening Failure\n");
        exit(1);
    }

    while(1) {
        size = sizeof(struct sockaddr_in);  

        if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size)==-1)) {
            //fprintf(stderr,"Accept Failure\n");
            perror("accept");
            exit(1);
        }

        printf("Server got connection from client %s\n", inet_ntoa(dest.sin_addr));
        //buffer = "Hello World!! I am networking!!\n";

        if ((num = recv(client_fd, buffer, 10239,0))== -1) {
            //fprintf(stderr,"Error in receiving message!!\n");
            perror("recv");
            exit(1);
        }   

        // num = recv(client_fd, buffer, sizeof(buffer),0);
        buffer[num] = '\0';
        printf("Message received: %s\n", buffer); 
        close(client_fd);   
        return 0;
        //close(socket_fd); 
    }    
}

クライアント:

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

#define PORT 3490

int main(int argc, char *argv[])
{
    struct sockaddr_in server_info;
    struct hostent *he;
    int socket_fd,num;
    char *buffer;

    if (argc != 2) {
        fprintf(stderr, "Usage: client hostname\n");
        exit(1);
    }

    if ((he = gethostbyname(argv[1]))==NULL) {
        fprintf(stderr, "Cannot get host name\n");
        exit(1);
    }

    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
        fprintf(stderr, "Socket Failure!!\n");
        exit(1);
    }

    memset(&server_info, 0, sizeof(server_info));
    server_info.sin_family = AF_INET;
    server_info.sin_port = htons(PORT);
    server_info.sin_addr = *((struct in_addr *)he->h_addr);
    if (connect(socket_fd, (struct sockaddr *)&server_info, sizeof(struct sockaddr))<0) {
        //fprintf(stderr, "Connection Failure\n");
        perror("connect");
        exit(1);
    }

    buffer = "Hello World!! I am networking!!\n";
    if ((send(socket_fd,buffer, sizeof(buffer),0))== -1) {
        fprintf(stderr, "Failure Sending Message\n");
        close(socket_fd);
        exit(1);
    }
    else {
        printf("Message being sent: %s\n",buffer);
    }

    close(socket_fd);   
}
4

2 に答える 2

1

サーバーを gdb で実行したところ、accept() の呼び出し後に client_fd が 0 であることがわかりました。これは無効なソケット fd であるため、そのコード行を確認したところ、閉じ括弧が間違っていることに気付きました。

if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size)==-1)) {

次のようにする必要があります。

if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size))==-1) {

それ以外の場合は、最初に比較を行ってから client_fd に比較を割り当てますが、ソケットの割り当てとその後の比較が必要です。

このような厄介なバグを回避するには、一般に、'if' ステートメント内に代入を置かないことがベスト プラクティスと考えられています。代わりにお勧めします:

client_fd = accept(...);
if (client_fd < 0) { ... }

また、クライアントでは、send() の呼び出しは「sizeof(buffer)」を使用します。'buffer' は char* で、ポインターのサイズは 4 (32 ビット システム上) であるため、'Hell' のみが送信されます。文字列全体を送信するには、送信する量の代わりに "strlen(buffer)" を使用します。

于 2012-07-09T01:41:43.450 に答える
0

最初の問題は、括弧の配置が間違っていることです。

if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size)==-1)) {

実際にあるはずです

if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size))==-1) {

あなたが現在持っているように、client_fdの戻り値との間の等値テストの結果に割り当てられるため、accept()成功-1した場合は常にゼロになります。

これが、多くのプログラマーが if ステートメントで代入を避ける理由の 1 つです。このように書くと

client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size);
if (client_fd == -1) {

その後、エラーは発生しません。

于 2012-07-09T01:34:35.797 に答える