Сокеты: соединение не установлено, соединение отклонено - PullRequest
0 голосов
/ 21 мая 2018

У меня есть приложение для сокетов, написанное на c, и я выполняю на linux, но когда я запускаю сервер (./server), я получаю следующую ошибку:

соединение не удалось, соединение отклонено.

Вот код:

server.c

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>

#define DEFAULT_PORT 8080

void error(char* message){
    perror(message);
    exit(EXIT_FAILURE);
}

void handler_client(void){
}

int main(int argc , char **argv[]){
    int server_fd;
    int new_socket;
    int valread;

    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};
    char *hello = "Hello, I'm server";

    if((server_fd = socket(AF_INET, SOCK_STREAM , 0)) == 0){
        error("socket failed");
    }

    if(setsockopt(server_fd , SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT , &opt , sizeof(opt))){
        error("setsockertopt");
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(DEFAULT_PORT);

    if(bind(server_fd , (struct sockaddr *)&address, sizeof(address) ) < 0){
        error("bind failure");
    }

    if(listen(server_fd , 3) < 0){
        error("listen");
    }

    if((new_socket = accept(server_fd , (struct sockaddr *)&address , (socklen_t *)&addrlen)) < 0){
        error("accept");
    }

    valread = read( new_socket , buffer , 1024);
    printf(" message from client : %s \n",buffer);
    send(new_socket , hello , strlen(hello) , 0);
    printf("Hello message sent \n");
    return 0;

 }

client.c

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

#define DEFAULT_PORT  8080
#define BUFFER_SIZE  1024

void error(char* message){
    perror(message);
    exit(EXIT_FAILURE);
}

int main(int argc , char** argv){
    struct sockaddr_in address;
    int sock = 0;
    int valread;
    struct sockaddr_in serv_addr;
    char message[BUFFER_SIZE] = {0};

    char buffer[BUFFER_SIZE] = {0};

    if((sock = socket(AF_INET , SOCK_STREAM , 0)) < 0){
        error("Sockert Creation fails");
    }

    memset(&serv_addr , '0' , sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(DEFAULT_PORT);

    if(inet_pton(AF_INET , "127.0.0.1" , &serv_addr.sin_addr) <= 0){
        error("Invalid address / Address not supported");
    }

    if(connect(sock , (struct sockaddr *)&serv_addr , sizeof(serv_addr) ) < 0){
        error("connection failed");
    }

    printf("enter your message : ");

    fgets(message , BUFFER_SIZE-1 , stdin);

    send(sock , message , strlen(message) , 0);
    printf("Hello message sent\n");
    valread = read(sock , buffer , BUFFER_SIZE);
    printf("response from buffer : %s\n",buffer);
    return 0;
}

1 Ответ

0 голосов
/ 21 мая 2018

Ошибка «отказано в соединении» означает, что вы пытаетесь подключиться к IP-адресу сервера: порт:

  1. не открыт для прослушивания

  2. имеет слишком много ожидающих клиентских подключений в своем бэклоге

  3. , заблокированных брандмауэром / маршрутизатором / антивирусом.

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

Поскольку ваш клиент пытается подключиться к 127.0.0.1, клиент и сервер ДОЛЖНЫ работать на одном компьютере.Вы не сможете подключиться через границы компьютера, включая границы виртуальных машин между системами хост / клиент.

При этом я вижу ряд ошибок в вашем коде, но ни одной из них, вызывающих ошибку подключения..

Сторона сервера:

  1. socket() возвращает -1 при ошибке, а не 0.

    //if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0){
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    
  2. youнельзя установить несколько параметров сокетов одновременно с setsockopt(), вы должны установить их индивидуально с отдельными вызовами на setsockopt().

    //setsockopt(server_fd , SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
    setsockopt(server_fd , SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    setsockopt(server_fd , SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
    

Сторона клиента:

  1. вы заполняете serv_addr '0' символами вместо 0 байтов.

    //memset(&serv_addr , '0' , sizeof(serv_addr));
    memset(&serv_addr, 0, sizeof(serv_addr));
    

С обеих сторон вы не делаете никакихобработка ошибок на send().Но что более важно, вы не включаете нулевой терминатор сообщения в отправку, поэтому у партнера нет возможности узнать, когда достигнут конец сообщения.TCP является потоковым транспортом, поэтому вам нужно поместить сообщения в протокол данных.Передайте длину сообщения перед отправкой самого сообщения.Или отправьте уникальный терминатор после сообщения.Затем узел может прочитать длину перед прочтением сообщения или прочитать, пока не будет достигнут терминатор.

Оба send() и read() возвращают, сколько байтов было фактически отправлено / получено, что может быть (и частоis) меньше байтов, чем запрошено.Вам нужно вызывать их в цикле, чтобы убедиться, что вы отправляете / получаете все, что ожидаете.

Кроме того, read() не возвращает строку с нулевым символом в конце, но использование printf() ожидает,Проверьте valread на наличие ошибок, и только если read() был успешным, передайте valread в printf() в качестве входного параметра, чтобы он знал, сколько данных на самом деле находится в buffer:

printf("message from client : %.*s\n", valread, buffer);

printf("response from buffer : %.*s\n", valread, buffer);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...