TCP服务器/客户端:客户端recv()返回空白缓冲区

时间:2018-03-03 17:45:22

标签: c++ sockets tcp send recv

我用C ++创建了一个TCP服务器/客户端。 客户端从stdin获取输入char数组。 然后客户端将其发送到服务器。 服务器的工作是使用来自客户端的修改形式的消息进行响应。 服务器的修改:用' X'

替换输入消息的第一个字符

它在第一个输入消息上按预期工作,但客户端从第二个消息开始接收格式错误的数据。

./ client.bin输出:

helloworld          <-----stdin
TX: helloworld
RX: Xelloworld
test                <-----stdin
TX: test
RX: 0est
somethingelse       <-----stdin
TX: somethingelse
RX: Xest

./ echoserver.bin输出:

RX: helloworld
TX: Xelloworld
RX: test
TX: Xest
RX: somethingelse
TX: Xomethingelse

echoserver.cc:

#include <iostream>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>   
#define  PORT 8080
#define  BUF_SIZE 1024

void error_exit(std::string text)
{
    std::cerr << text << std::endl;
    exit(1);
}

int main()
{
    int sd;
    int connection;
    int valread;
    int opt = 1;
    char buffer[BUF_SIZE] = {0};
    if ((sd = socket(AF_INET,SOCK_STREAM,0)) == 0)
        error_exit("socket failure");

    if (setsockopt(sd, SOL_SOCKET,SO_REUSEADDR,
            &opt, sizeof(opt)))
        error_exit("failed to set socket opts");

    sockaddr_in address;
    address.sin_family      = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port        = htons(PORT);
    if (bind(sd, (struct sockaddr *)&address, sizeof(address)) != 0)
        error_exit("failed to bind socket");

    if (listen(sd,3) < 0)
        error_exit("failed to listen");

    int addrlen = sizeof(address);
    if ((connection = accept(sd, (struct sockaddr*)&address,
                    (socklen_t*)&addrlen)) < 0)
        error_exit("failed to accept socket link");

    while (1)
    {
        memset(&buffer[0],'0', sizeof(buffer));
        if (recv(connection,buffer,BUF_SIZE-1,0) <= 0)
            break;
        std::cout << "RX: " << buffer << std::endl;
        buffer[0] = 'X';
        std::cout << "TX: " << buffer << std::endl;
        send(connection,buffer,BUF_SIZE,0);
    }
    return 0;
}

client.cc

#include <iostream>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUF_SIZE 1024

void error_exit(std::string text)
{
    std::cerr << text << std::endl;
    exit(1);
}

int main()
{
    int sd;
    int valread;
    struct sockaddr_in address;
    struct sockaddr_in server_addr;
    char buffer[BUF_SIZE] = {0};

    if ((sd = socket(AF_INET,SOCK_STREAM,0)) < 0)
        error_exit("failed to create socket");

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

    server_addr.sin_family = AF_INET;
    server_addr.sin_port   = htons(PORT);

    if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0)
        error_exit("Invalid Address");

    if (connect(sd,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)
        error_exit("Connection Failure");

    std::cin >> buffer;
    while (buffer[0] != 'q')
    {
        std::cout << "TX: " << buffer << std::endl;

        send(sd,buffer,BUF_SIZE-1,0);
        if ( recv(sd,buffer,BUF_SIZE-1,0) <= 0)
            error_exit("Failed to receive");
        std::cout << "RX: " << buffer << std::endl;
        memset(&buffer[0],'0', sizeof(buffer));
        std::cin >> buffer;
    }
    return 0;
}

1 个答案:

答案 0 :(得分:2)

您的发送呼叫始终发送1023个字节,但您的recv呼叫不一定下载所有数据,您需要在循环中调用recv,直到您拥有所有已发送的数据或传递MSG_WAITALL标志。