c - C 中 send()、recv() 的一些 EOF 机制

标签 c sockets

我想知道,如果我用 C 语言编写的客户端执行 4 个 send() 操作,我的服务器是否需要 read() 4 次,或者第一次读取是否会读取所有 4 个 send() 的所有内容在一起吗?

最佳答案

为了帮助您一点,您基本上已经回答了自己的问题。

可以这么说,您需要“分层”进行。

客户:

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);
}

该函数正好接收一个无符号整数,并将字节顺序从网络字节顺序更正为主机字节顺序。 (网络字节顺序始终为大端,主机字节顺序通常为:小端)

使用这些包装函数,代码可以更改如下:

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.

关于c - C 中 send()、recv() 的一些 EOF 机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15116053/

相关文章:

c - 为什么 GCC 会为几乎相同的 C 代码生成如此截然不同的程序集?

c - 从 fifo C 读取

c - C语言的猜字游戏

java - DatagramSocket.receive() 和 SocketException

c# - 通过 Socket 传输视频帧

c - 我无法将 stren 与指针一起使用

c - 在 C 和 C++ 中使用结构

.net - 如何使用powershell连接到tcp socket发送和接收数据?

node.js - 使用 Socket.io 和 Redis 的 Node 集群问题

php - socket_recv(): unable to read from socket [0]: The operation completed successfully