我想知道,如果我用我的客户端做4发送(),用C语言编写,我的服务器需要读取()4次,还是第一次读取将读取所有4次发送()全部一起?
答案 0 :(得分:4)
为了帮助你一点点,你基本上已经回答了你自己的问题。
你需要在“层级”中这样做,可以这么说。
客户端:
int len = strlen(Filename) + 1; //Mind the terminating 0.
send(sock, (const char *)&len, sizeof(int), 0);
send(sock, Filename, len, 0); //Sending the filename
send(sock, &FileSize, sizeof(int), 0);
send(sock, FileBuf, FileSize, 0);
此代码将在途中发送整个数据(假设整个文件位于'FileBuf'变量中)。
服务器:
int len;
char *FileBuf, FileName[20];
recv(sock, &len, sizeof(int), 0); //Receives the filename length. (4 Bytes)
recv(sock, FileName, len, 0); //Receives the filename (x bytes)
recv(sock, &len, sizeof(int), 0); //Receives the file length (again, 4 bytes)
FileBuf = new char[len]; //Creates sufficient space in memory.
recv(sock, FileBuf, len, 0); //Receives the file into the appropriate variable.
这是绝对的准系统变体,不是很稳固,但你应该明白这一点。
更强大的方法要求您检查recv()和send()的返回值。两者都将返回已使用此调用处理的字节数。如果此金额等于'0',则表示连接已被另一端关闭。 (主要针对recv()
)。如果它等于-1,则表示出现了问题,您应该检查errno
变量。
如果一切顺利,它等于您发送/尝试接收的确切字节数。
但是如果它不是'len'(或0或-1),你可以写一个像这样的小包装。
unsigned char Recv(int sock, void *target, int Len) {
unsigned char *ptr = (unsigned char *)target, Ret = 0;
int RecvBytes = 1;
while(Len && !Ret) {
RecvBytes = recv(sock, ptr, Len, 0);
if(!RecvBytes) Ret = 1;
else if(RecvBytes == -1) Ret = errno;
else {
Len -= RecvBytes;
ptr += RecvBytes;
}
}
return Ret;
}
此代码的作用:它一直接收,直到您收到了您期望的所有数据(Len
参数)或发生错误。如果一切顺利,则返回“0”,您可以使用if(!Recv())
进行检查。
另一个有用的包装函数(可以这么说的快捷方式)就是这个:
uint32_t RecvInt(int sock) {
uint32_t Ret;
Recv(sock, &Ret, sizeof(Ret));
return ntohl(Ret);
}
此函数只接收一个unsigned int,并将字节顺序从网络字节顺序更正为主机字节顺序。 (网络字节顺序总是大端,主机字节顺序通常是:小端)
使用这些包装函数,代码可能会改变如下:
uint32_t len;
char *FileBuf, FileName[20];
len = RecvInt(sock); //Receives the filename length. (4 Bytes)
Recv(sock, FileName, len); //Receives the filename (x bytes)
len = RecvInt(sock); //Receives the file length (again, 4 bytes)
FileBuf = new char[len]; //Creates sufficient space in memory.
Recv(sock, FileBuf, len); //Receives the file into the appropriate variable.
答案 1 :(得分:1)
对于流套接字(例如TCP):在发送端进行了多少send()
或write()
次呼叫没有区别。数据可以在少至一个块中返回,多达n个块,每个块1个字节(其中n是发送的字节数),或者介于两者之间的任何内容。
对于数据报套接字(例如UDP):每个recv()
或recvmsg()
调用将返回从另一端发送的一个完整数据报。 recv()
或recvmsg()
次呼叫的数量应与已发送的数据报数量相同。从数据报套接字读取时首选recv()
,但我相信read()
的行为应该相同。
答案 2 :(得分:0)
write()
和read()
的数量不一定相同 - write()
可能将所有数据写入一个部分,但在另一台计算机上{ {1}}仅设法以几个块接收它,反之亦然。这就是为什么你应该总是检查这些函数的返回值,如果只发生部分数据传输,那么继续发送/接收其余的数据。