Сброс соединения путем программирования одноранговых сокетов

Я получаю сообщение об ошибке в коде на стороне клиента о соединение сброшено узлом, когда я вызываю функцию Отправить из клиента --> сервера. Я посмотрел это в Интернете, но я не совсем понимаю, может ли кто-нибудь объяснить, что вызывает эту ошибку и почему?

Это код клиентского сокета. Я заставил его принимать сервер на 127.0.0.1.

КЛИЕНТ.С

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

#define SERVER_PORT 9002
#define BUFSIZE 4096
#define SOCKETERROR (-1)
#define SERVER_BACKLOG 1

typedef struct sockaddr_in SA_IN;
typedef struct sockaddr SA;

struct sockaddr_in init_socket(const char* address);
void check(int output,const char* msg);

int main(int argc,char** argv){

int     number = 0;
int     client_socket;
SA_IN   client_address;


check((client_socket = socket(AF_INET,SOCK_STREAM,0)),"[SERVER] : cannot create socket");
client_address = init_socket("127.0.0.1");
check(connect(client_socket,(struct sockaddr*)&client_address,sizeof(client_address)),"[CLIENT]--(connect)--->[SERVER] ");

 while(1){ 
    if (send(client_socket,&number,sizeof(number),0),"[CLIENT]-------->[SERVER] " > 0){

        number++;
        if (number == 100) break;
        printf("[CLIENT] : %d\n",number);

        check(recv(client_socket,&number,sizeof(int),0),"[CLIENT]-------->[SERVER] ");
    }
}
close(client_socket);
return 0;
}

struct sockaddr_in init_socket(const char* address){
    struct sockaddr_in server_address;
    server_address.sin_family       = AF_INET; 
    server_address.sin_port         = htons(SERVER_PORT);
    // server_address.sin_addr.s_addr  = INADDR_ANY;
    server_address.sin_addr.s_addr  = inet_addr(address);
    return server_address;
}

void check(int output,const char* msg){
    if (output < 0){
        perror(msg);
        exit(1);
    }
}

Это код серверного сокета. Он принимает клиентов с любого адреса (INADDR_ANY).

СЕРВЕР.C

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

#define SERVER_PORT 9002
#define BUFSIZE 4096
#define SOCKETERROR (-1)
#define SERVER_BACKLOG 1

typedef struct sockaddr_in SA_IN;
typedef struct sockaddr SA;

void handle_connection(int client_socket);
struct sockaddr_in init_socket();
void check(int output,const char* msg);

int main(int argc,char** argv){

    int     number;
    int     server_socket   , client_socket;
    SA_IN   server_address  ,client_address;
    
    check((server_socket = socket(AF_INET,SOCK_STREAM,0)),"[SERVER] : cannot create socket");
    server_address = init_socket();
    check(bind(server_socket,(SA*)&server_address,sizeof(server_address)),"[SERVER] : binding error");
    check((client_socket = listen(server_socket,SERVER_BACKLOG)),"[SERVER] : listen failed");

     while(1){ 
        if (recv(client_socket,&number,sizeof(int),0) > 0){


            number++;
            if (number == 100) break;
            printf("[SERVER] : %d\n",number);

            check(send(client_socket,&number,sizeof(number),0),"[SERVER]-------->[CLIENT]: ERROR");
        }
    }
    close(server_socket);
    return 0;
}

struct sockaddr_in init_socket(){
    struct sockaddr_in server_address;
    server_address.sin_family       = AF_INET; 
    server_address.sin_port         = htons(SERVER_PORT);
    server_address.sin_addr.s_addr  = INADDR_ANY;
    return server_address;
}

void check(int output,const char* msg){
    
    if (output < 0){
        fprintf(stderr,"%s\n",msg);
        exit(1);
    }
}

🤔 А знаете ли вы, что...
C имеет низкоуровневый характер, что позволяет разработчикам более точно управлять ресурсами компьютера.


21
1

Ответ:

Решено

«Соединение, сброшенное узлом» — это именно то, на что это похоже: «Узел» (другая сторона соединения) закрыл соединение.

Обычно вы обнаруживаете это, проверяя, доступен ли сокет для чтения, и когда read (или recv) возвращает 0.

Если вы не обнаружите это таким образом и вместо этого попытаетесь записать в сокет, вы получите ту ошибку, которую вы получаете.

Если вы получите эту ошибку (или обнаружите закрытое соединение другим способом), вам следует закрыть конец соединения.


Конкретная проблема с вашим кодом заключается в том, что ваша функция check проверяет только ошибки, а не другие условия, которые могут применяться (например, закрытое соединение).

Почти всегда рекомендуется сохранять то, что возвращает read или recv, в переменной, которую можно проверить на наличие явных ошибок (-1), закрытого соединения (0) или успешно полученных данных (> 0).