Информация

Проблема: я пытаюсь настроить TCP-сокет read() и write() из одной и той же основной функции, однако я не уверен, как правильно читать из сокета.

Справочная информация . У меня есть связь, работающая с отдельными исполняемыми файлами: один для чтения (сервер), а другой для записи (клиент).

Для этого я использовал этот сайт для руководства. https://www.geeksforgeeks.org/tcp-server-client -внедрение -в- с /

Из комментария Реми Лебо я понимаю, что сокет C читает и пишет, что сокет возвращен { {X0}} используется сервером, а сокет, возвращенный из socket(), используется клиентом.

У меня запись в сокет работает правильно.

Awaiting message from a client...
Address: 2, Port: 4547
Socket: 4
Serv addr: -1894572528
Size of server: 16
Message to send to server: hey
sendBytes: 3: hey
Recv bytes: 0
Recieved message: 

Код

Программа состоит из трех функций

< Сильный > Основной ( )

< Сильный > createTcpRcvSock ( )

< Сильный > createTcpSendSock ( )

Функции заголовков и их тел

main (), включает в себя и определения

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

#define PORT 4547
int main(){

    int recvSock,sendSock,recvN,sendN,bufferSize,acceptSock,clilen;
    struct sockaddr_in cli_addr;

    char sendBuffer[256];
    char recvBuffer[256];

    recvSock = createTcpRecvSock();

    clilen = sizeof(cli_addr);

    acceptSock = accept(recvSock, (struct sockaddr *)&cli_addr, clilen);

    sendSock = createTcpSendSock();

    printf("Message to send to server: ");

    bzero(sendBuffer,256);
    scanf("%s",&sendBuffer);
    bufferSize = strlen(sendBuffer);
    sendN = write(sendSock,sendBuffer,bufferSize);
    printf("sendBytes: %d: %s\n",sendN,sendBuffer);
    if(sendN < 0){
        printf("Error writing to socket\n");
    }

    bzero(recvBuffer,256);
    bufferSize = strlen(recvBuffer);
    recvN = read(acceptSock,recvBuffer,bufferSize);
    printf("Recv bytes: %d\n", recvN);
    if(recvN < 0){
        printf("Error reading from socket\n");
    }
    printf("Recieved message: %s\n",recvBuffer);
}

< Сильный > createTcpSendSock ( )

int createTcpSendSock(){
    int sockfd;
    struct sockaddr_in serv_addr;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0){
        error("ERROR opening socket");
    }
    bzero((char *) &serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(PORT);

    printf("Socket: %d\n", sockfd);
    printf("Serv addr: %d\n", &serv_addr);
    printf("Size of server: %d\n", sizeof(serv_addr));

    if (connect(sockfd,(struct sockaddr *)&serv_addr ,sizeof(serv_addr)) < 0){ 
        printf("Error connecting: %d:  %s\n",errno,strerror(errno));
    }
    return sockfd;
} 

< Сильный > createTcpRecvSock ( )

int createTcpRecvSock(){

    int sockfd,portno,clilen,opt;
    struct sockaddr_in serv_addr;

    opt = 1;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        error("ERROR opening socket");
    }
    printf("Success opeing socket\n");

    bzero((char *) &serv_addr, sizeof(serv_addr));

    if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))){
        printf("Setting socket options error: %d: %s\n",errno, strerror(errno));
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(PORT);

    printf("Awaiting message from a client...\n");
    printf("Address: %d, Port: %d\n", AF_INET, PORT);

    if(
    bind(sockfd,
    (struct sockaddr *) &serv_addr, 
    sizeof(serv_addr))
     < 0)
    {
        printf("Error on binding: %d, %s\n",errno, strerror(errno));
    }
    listen(sockfd,6);

    return sockfd;
}

<Сильные> Ожидаемые

Я ожидал бы вывод Received message: <User entered message>

Фактический

Но программа зависает на этом, хотя цикла нет:

Success opeing socket
Awaiting message from a client...
Address: 2, Port: 4547

Любая помощь будет принята с благодарностью, я постарался сделать ее максимально удобочитаемой.

-1
Teale 7 Окт 2019 в 12:24

2 ответа

Лучший ответ

Как указал пользователь user207421 , я принимал клиента перед подключением.

Также acceptSock = accept(recvSock, (struct sockaddr *)&cli_addr, clilen);

Должно быть acceptSock = accept(recvSock, (struct sockaddr *)&cli_addr, &clilen);

socklen_t *addrlen параметр accept() требует указателя, я не передавал указатель.

Добавление & перед параметром размера изменит это.

0
Teale 8 Окт 2019 в 06:25

Не используйте строковые функции, если вы знаете длину другим способом. Это доставит вам неприятности.

bzero(recvBuffer,256);
bufferSize = strlen(recvBuffer);
recvN = read(acceptSock,recvBuffer,bufferSize);

Вы очищаете буфер, чтобы он содержал только нули. Поскольку нулевые байты отмечают конец строки, strlen вернет ноль. Итак, вы пытаетесь читать с буфером, размер которого равен нулю.

Функция strlen НИКОГДА не говорит вам, сколько места доступно. Он говорит вам, насколько большие строковые данные. Если там нет строковых данных, то нет смысла вызывать strlen.

Затем вы делаете это:

printf("Recieved message: %s\n",recvBuffer);

Хотя он, вероятно, будет работать с тем, как ваш код в настоящее время, это плохая привычка. Функция read вернула recvN количество полученных вами байтов. Вы игнорируете это и просите printf выяснить, что печатать только из данных. Не делай этого. В конечном итоге это доставит вам неприятности. Используйте recvN, чтобы узнать, сколько байтов нужно напечатать.

0
David Schwartz 7 Окт 2019 в 09:32