从客户端套接字获取命令序列

时间:2014-11-14 03:06:10

标签: c sockets

我正在编写一个基本的服务器/客户端对话框,客户端发送命令后跟几个参数。

例如:

(<command> <arg1> <arg2>\n<final arg>)
//client input: 
CREATE somefile.txt 19\n
some file text here

服务器解析命令,并执行操作。这是我的问题;&#39; \ n&#39;字符意味着其余的参数将在下一个发送()&#39;中提供。因此,在示例中,文件的文本在前几个参数之后出现。

&#39;错误&#39;这里是如果快速发送文件文本,这两个命令似乎放在同一个缓冲区中。

在以下示例中会出现这种情况:

//INSIDE CLIENT.C:

//INPUT 1: causes trouble
write( sock, command, strlen( command ) );
write( sock, filecontents, strlen( filecontents ) );     

//INPUT 2: works fine
write( sock, command, strlen( command ) );
sleep(1);
write( sock, filecontents, strlen( filecontents ) );     

//INSIDE SERVER.C:
int len = recv(client_socket, args, buffer_size, 0);//get the initial args <CREATE> <FILENAME> <BYTES>
printf("command:%s", args);

//code to parse the command and call relevant method
...
//in the "Create file" method, we wait for the contents of the file
int len = recv( client->client_socket, contents, buffer_size, 0);
printf("contents:%s", contents);

输出取决于客户端write()s:

之间的时间量
//OUTPUT 1: without sleep():
//The first recv gets all the data, 
//then the next recv gets the whole message again (from the next client iteration, 
command:CREATE file.txt 19
some file text here
contents:CREATE file.txt 19
some file text here

//OUTPUT 2: with sleep(): 
command:CREATE file.txt 19
contents:some file text here

目标: 我每次都需要它看起来像输出2。问题是,我无法控制客户端的操作,因此sleep()不是永久的解决方案。我应该怎么解决这个问题?

注意:我非常确定通过更改recv的处理方式可以解决问题,因此我不会想到需要更多代码。如果我发帖更多,请告诉我。

编辑:我唯一知道的是,初始命令即CREATE file.txt 89\n将始终以&#39; \ n&#39;无论。如果recv()一次收到所有数据,那么我就可以读到第一个&#39; \ n&#39;。但是当情况不是这样时,消息(和缓冲区)被分成两部分,如下例所示:

CASE 1:
int len = recv( client->client_socket, args, buffer_size, 0);
//args == "CREATE file.txt 19\nsome file text here"

CASE 2:
int len = recv( client->client_socket, args, buffer_size, 0);
//args == "CREATE file.txt 19\n"

CASE 3://<--might have made this one up, could not reproduce
int len = recv( client->client_socket, args, buffer_size, 0);
//args == "CREATE file.txt 19\n" <--- this means I have to recv again

int len2 = recv( client->client_socket, args, buffer_size, 0);
//possibilities:
//
//the second recv() might contain:
//args == "CREATE file.txt 19\nsome file text here"
//or
//args == "some file text here"

在案例1中,在第一个recv中检索所有数据,所有数据都在一个缓冲区中。 在情况2中,前半部分存储在缓冲区中。现在,在这种情况下,我知道我需要等待其余的数据到达。但是,到它到达时,我怎么知道缓冲区中的数据是否仍包含&#34;创建&#34;部?

//I would need something like this:
if(commands still in buffer from recv, and the text file data has arrived)
{
     //then skip over those args, and begin reading form a different index
}
else {
     //read the data from the start.
}

但是我无法想出办法来做到这一点......这有意义吗?

1 个答案:

答案 0 :(得分:2)

你不应该那么信任网络。

正如您所发现的,recv()只会收到个人send()的数据。您的字节从send()函数到recv()的路径中涉及很多缓冲,所以没有人会保证这一点。

我建议你 - do advise at University :) - 实现某种使用固定长度字段来了解可变长度数据的协议。

例如,您可以通过在4个字节之前发送指示要发送的实际数据字节数,然后是您想要的数据来启动要发送的每条消息。在接收器上,首先是recv(),固定大小为4个字节,然后分配一个字节块,该字节块的数量与该数字所代表的一样多,最后你recv()那个字节很多。

通过这种方式,您始终知道要接收多少数据,何时分割数据等等 - 至少as much as the network lets you

此外,请勿忘记检查send()recv()返回值,因为它们可能表示您仍然缺少某些字节 - 并在需要时重试。