c - (C 套接字编程)来自服务器的单独 send() 调用在同一个客户端 recv() 缓冲区中结束

标签 c sockets tcp ubuntu-14.04

我想知道是否有人可以阐明为什么两个单独的 send() 调用最终会在同一个 recv() 缓冲区中使用环回地址进行测试,但一旦切换到两台远程机器,他们将需要两个 recv( ) 调用?我一直在查看 wireshark 捕获,但似乎无法理解为什么会发生这种情况。也许有人可以批评我的代码并告诉我哪里出了问题。来自服务器的两个传入消息对于客户端来说是不确定的长度。顺便说一下,我在 Ubuntu 中使用 C 来使用 BSD 套接字。

在下面显示的示例中,我将解析整个缓冲区以从中提取两条单独的消息,我承认这不是理想的方法。

--------服务器端--------

// Send greeting string and receive again until end of stream
ssize_t numBytesSent = send(clntSocket, greeting, greetingStringLen, 0);
if (numBytesSent < 0)
  DieWithSystemMessage("send() failed");

//-----------------------------Generate "RANDOM" Message -----------------------

srand(time(NULL)); //seed random number from system clock

size_t randomStringLen = rand() % (RANDOMMSGSIZE-3); //generates random num
                                                     // betweeen 0 and 296

char randomMsg [RANDOMMSGSIZE] = "";

// declare and initialize allowable characteer set for the
const char charSet[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (randomStringLen) {
    --randomStringLen;
    for (size_t i = 0; i < randomStringLen; i++) {
        int p = rand() % (int) (sizeof charSet - 1);
        randomMsg[i] = charSet[p];
    }
    randomStringLen = strlen(randomMsg);
    printf("Random String Size Before newline: %d\n", (int)randomStringLen);

strcat(randomMsg,"\r\n");
}

randomStringLen = strlen(randomMsg);

printf("Random String: %s\n", randomMsg);

//-----------------------------Send "RANDOM" Message ---------------------------

// Send greeting string and receive again until end of stream
numBytesSent = send(clntSocket, randomMsg, randomStringLen, 0);
if (numBytesSent < 0)
  DieWithSystemMessage("send() failed");

//------------------------------------------------------------------------------

------客户端--------

//----------------------------- Receive Server Greeting ---------------------------

char buffer[BUFSIZE] = ""; // I/O buffer
// Receive up to the buffer size (minus 1 to leave space for
// a null terminator) bytes from the sender
ssize_t numBytesRcvd = recv(sock, buffer, BUFSIZE - 1, 0);

if (numBytesRcvd < 0)
  DieWithSystemMessage("recv() failed");
buffer[numBytesRcvd] = '\0'; //terminate the string after calling recv()

printf("Buffer contains: %s\n",buffer); // Print the buffer

//printf("numBytesRecv: %d\n",(int)numBytesRcvd); // Print the buffer


//------------------------ Extracts the random message from buffer ---------------------------

char *randomMsg = strstr(buffer, "\r\n"); // searches from first occurance of substring
char randomMessage [BUFSIZE] = "";
strcat(randomMessage, randomMsg+2);

int randomStringLen = strlen(randomMessage)-2;

printf("Random Message: %s\n",randomMessage); // Print the buffer

char byteSize [10];
sprintf(byteSize,"%d", randomStringLen);
printf("ByteSize = %s\n",byteSize);

//----------------------- Send the number for random bytes recieved -------------------------

size_t byteStringLen = strlen(byteSize); // Determine input length

numBytes = send(sock, byteSize, byteStringLen, 0);
if (numBytes < 0)
  DieWithSystemMessage("send() failed");
else if (numBytes != byteStringLen)
  DieWithUserMessage("send()", "sent unexpected number of bytes");

shutdown(sock,SHUT_WR); // further sends are disallowed yet recieves are still possible

//----------------------------------- Recieve Cookie ----------------------------------------

最佳答案

在 Unix 系统上,recvsend 只是 readwrite 的特例,它们接受额外的标志. (Windows 也使用 Winsock 模拟这一点)。

你不应该假设一个 recv 对应一个 send 因为这通常是不正确的(就像你可以读取多个部分的文件一样,即使它是一次写成的)。相反,您应该在每条“消息”的开头加上一个 header , header 告诉您消息的长度,如果知道单独的消息是什么很重要,或者如果它不重要,则像普通文件一样读取流。

关于c - (C 套接字编程)来自服务器的单独 send() 调用在同一个客户端 recv() 缓冲区中结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27096243/

相关文章:

java - 一个 java UDP 套接字可以处理多少个请求?

python - 使用 Blender Python 与纯数据的 TCP 连接

c - 如何确保生成的 config.h 文件在包含路径中?

c - 8051 μCU - 如何处理并发中断?

vb.net - 返回IP地址/端口的套接字属性

c - 检测连接

c# - 当从其他机器监听数据时,请求的地址在其上下文中无效

c - 如何找出套接字的传输/接收字节数

c - 如何使用 GObject 按名称调用函数?

c - OpenCV中两点之间的距离