我正在测试我的TCP echo服务器,使用Telnet,我可以看到客户端连接到服务器并发送一个charcter,作为回报,服务器将一个字符串返回给客户端。
现在我的问题是在无限循环中使用这个recv()我只能收到一个字符(即使客户端倾向于发送一个字符串)。
这就是我从客户端接收数据报的方式
TCP服务器
while(1)
{
socket = accept(server_socket, (struct sockaddr *)&client_address, (socklen_t)&client_length);
recv(socket, recv_buffer, sizeof(recv_buffer), 0);
printf("Received string from client is %s", recv_buffer);
/*then I send my string to the client*/
send(socket, send_buffer, sizeof(send_buffer), 0);
}
这是我的问题,即使客户端想要发送整个字符串,我的recv()例程也只读取一个字符。有没有办法让我可以让这个recv()例程在从客户端收到所有字符然后向客户端发送响应之前等待。
任何建议都将不胜感激
此致
答案 0 :(得分:1)
嗯,你做错了什么。查看recv
:
int recv(int s, void *buf, size_t len, int flags);
因此它收到了len
个字节数。您将sizeof(recv_buffer)
作为len参数传递。现在我猜测recv_buffer
被定义为char*
。获取指针的sizeof
意味着您获得存储该指针所需的字节数,而不是它指向的内存。
做这样的事情:
const int buf_len = 100;
char recv_buffer[buf_len];
recv(socket, recv_buffer, buf_len, 0);
printf("Received string from client is %s", recv_buffer);
答案 1 :(得分:1)
您需要在循环中构建自己接收的字符串,使用recv()
的返回值来查找实际获得的字节数。 TCP / IP不保证通过一次send()
呼叫可以接收通过一次呼叫recv()
发送的所有数据。并且您必须检查您调用的每个套接字函数的返回值,以检查发送/接收的实际长度以及错误。
答案 2 :(得分:1)
你的代码是一场灾难(对不起直言不讳,但最好直截了当。)
recv()返回实际读取的字节数。不仅如此,它还不会清除缓冲区的先前内容,如果有可用数据,它将填充到缓冲区的末尾。所有这些意味着您不能将缓冲区的内容视为以空字符结尾的字符串。
您需要执行以下操作:
ssize_t bytesRead = 1;
char recv_buffer[SOME_SIZE];
while (bytesRead > 0)
{
int bytesRead = recv(socket, recv_buffer, SOME_SIZE, 0);
if (bytesRead > 0)
{
// do something with the bytes. Note you cannot guarantee that the buffer contains a valid C string.
}
}
if (bytesRead == -1)
{
// report error from errno
}
else
{
// bytesRead == 0 have reached end of file (i.e. socket closed at other end)
}
在返回之前,无法让recv等到缓冲区已满。它会等到有一些字节可用然后返回。这同样适用于顺便发送。您不能假设一次调用发送所有字节实际上已发送。你也需要把send放在一个循环中:
ssize_t totalBytesWritten = 0;
ssize_t bytesWritten = 0;
while (bytesWritten >= 0 && totalBytesWritten < bytesToWrite)
{
bytesWritten = send(socket, sendBuffer + totalBytesWritten, bytesToWrite - totalBytesWritten, 0);
if (bytesWritten > 0)
{
totalBytesWritten += bytesWritten;
}
}
if (bytesWritten == -1)
{
// error
}