(C 套接字编程)来自服务器的单独 send() 调用在同一客户端 recv() 缓冲区中结束 [英] (C Socket Programming) Seperate send() calls from server ending up in same client recv() buffer

查看:50
本文介绍了(C 套接字编程)来自服务器的单独 send() 调用在同一客户端 recv() 缓冲区中结束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was wondering if anyone could shed any light as to why two seperate send() calls would end up in the same recv() buffer using the loopback address for testing yet once switched to two remote machines they would require two recv() calls instead? I have been looking at the wireshark captures yet cant seem to make any sense as to why this would be occuring. Perhaps someone could critique my code and tell me where im going wrong. The two incoming messages from the server is of an undetermined length to the client. By the way i'm using BSD sockets using C in Ubuntu.

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

In the example shown below im parsing the entire buffer to extract the two seperate messages from it which i'll admit isn't an ideal approach.

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

-------SERVER SIDE--------

// 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");

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

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

------CLIENT SIDE-------

//----------------------------- 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 模拟了这一点).

On Unix systems recv and send are just special cases of the read and write that accepts additional flags. (Windows also emulates this with Winsock).

你不应该假设一个 recv 对应一个 send 因为这通常不是真的(就像你可以读取多个部分的文件,即使它是在一次写入中写入的).相反,您应该在每个消息"开始时使用一个标头来告诉您消息的长度,如果知道单独的消息是什么很重要,或者只是像普通文件一样读取流,如果它不重要.

You shouldn't assume that one recv corresponds to one send because that's generally isn't true (just like you can read a file in multiple parts, even if it was written in a single write). Instead you should start each "message" with a header that tells you how long the message is, if it's important to know what were the separate messages, or just read the stream like a normal file, if it's not important.

这篇关于(C 套接字编程)来自服务器的单独 send() 调用在同一客户端 recv() 缓冲区中结束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆