C TCP write () и read () из сокетов, определенных в main - PullRequest
0 голосов
/ 07 октября 2019

Информация

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

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

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

Из комментария Реми Лебо я понимаю, что C-сокет читает и пишет , что сокет, возвращаемый accept(), используется Сервером, а сокет возвращается из 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: 

Код

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

main ()

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

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

Ответы [ 2 ]

0 голосов
/ 08 октября 2019

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

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

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

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

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

0 голосов
/ 07 октября 2019

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

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...