Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何通过套接字发送位字段?_C_Sockets_Networking - Fatal编程技术网

C 如何通过套接字发送位字段?

C 如何通过套接字发送位字段?,c,sockets,networking,C,Sockets,Networking,我需要从客户端向服务器发送一组位字段和一个字符串 因此,我有: #define YES 1 #define FLAG 2 int main(int argc, char* argv[]) { return sendToServer("The Message", YES | FLAG); } int sendToServer(char* msg, int bitfields) { /* create socket and connect to server */ /* Assu

我需要从客户端向服务器发送一组位字段和一个字符串

因此,我有:

#define YES 1
#define FLAG 2
int main(int argc, char* argv[])
{
    return sendToServer("The Message", YES | FLAG);
}
int sendToServer(char* msg, int bitfields)
{
   /* create socket and connect to server */
   /* Assume sock is set */
   send(sock, msg, strlen(msg), 0);
   return 0;
}
发送位字段的最佳方式是什么?是否仍然可以将位字段与字符串一起发送

编辑:好的,我正在尝试实现Vlad的方法。我的当事人和他写的几乎一模一样。我已在开始数据[0]处放置了标志,并使用了htonl而不是bswap。我的服务器:

int main(int argc, char* argv[])
{
    /* create socket and wait for connection */
    char buffer[BUFFERSIZE];
    size_t rcvdB = recv(clntSock, buffer, sizeof(int),0);
    int flags = ntohl((int) buffer);
    rcvdB = recv(clntSock, buffer, sizeof(size_t),0);
    size_t msgSize = ntohl((size_t) buffer);
    rcvdB = recv(clntSock,buffer,msgSize,0);
    /* Then I send back to the client */
    ssize_t sntB = send(clntSock,buffer,msgSize,0);
}
当客户端打印消息时,消息末尾有多个ascii字符

编辑2:


当我读取超过8个字节的数据时,问题似乎会出现。位字段形成一个数字,例如1 | 2给出3,因为%01 |%10=%11

所以你只需要发送那个号码。有点

snprintf(buffer, buffer_size, "%s-%d", message, number);
send(sockfd, buffer, buffer_size, 0);

位字段形成一个数字,例如1 | 2给出3,因为%01 |%10=%11

所以你只需要发送那个号码。有点

snprintf(buffer, buffer_size, "%s-%d", message, number);
send(sockfd, buffer, buffer_size, 0);

最好将位字段作为原始int的字节发送,例如sendsock、&bitfields、sizeofbitfields、0,确保客户端和服务器的大小和endianness相同。发送字符串之前的位可能最容易,因为服务器可以在固定字节数之后轻松提取字符串。

最好将位字段作为原始整数的字节发送,例如sendsock、&bitfields、sizeofbitfields、0,确保客户端和服务器的大小和endianness相同。发送字符串之前的位可能最容易,因为服务器可以在固定字节数之后轻松提取字符串。

当然,这取决于您的网络协议。如果您正在设计它,并且最多可以发送8个标志,请将它们放在消息的第一个字节中。如果您最多有16个,但它们位于前两个字节中,以此类推

int sendToServer(int sock, char* msg, int flags)
{
    size_t siz = strlen(msg) + 1;  // +1 for NUL
    unsigned char *buf = malloc_or_die(siz + 1);
    buf[0] = flags;
    memcpy(buf + 1, msg, size);

    send(sock, msg, strlen(msg), 0);

    free(buf);
    return 0;
}

我将位字段更改为标志,因为它们就是这样。位字段是标志的集合。

这当然取决于您的网络协议。如果您正在设计它,并且最多可以发送8个标志,请将它们放在消息的第一个字节中。如果您最多有16个,但它们位于前两个字节中,以此类推

int sendToServer(int sock, char* msg, int flags)
{
    size_t siz = strlen(msg) + 1;  // +1 for NUL
    unsigned char *buf = malloc_or_die(siz + 1);
    buf[0] = flags;
    memcpy(buf + 1, msg, size);

    send(sock, msg, strlen(msg), 0);

    free(buf);
    return 0;
}

我将位字段更改为标志,因为它们就是这样。位字段是标志的集合。

正如其他人所指出的,它取决于协议。我会用这样的方法:

int sendToServer(char* msg, int bitfields)
{
   unsigned int bits = bswap32 (bitfields); // Convert host to network byte order.

   size_t len = strlen (msg);   // Calculate string length.
   size_t nlen = bswap64 (len); // Convert length's byte order from host to network.

   iovec data[3]; // Prepare 3 I/O buffers to send data by performing a single system call (they are expensive).

   // Send length of the string first.
   data[0].iov_base = &nlen;
   data[0].iov_len = sizeof (nlen);

   // Send string...
   data[1].iov_base = msg;
   data[1].iov_len = len;

   // And, of course, send bits.
   data[2].iov_base = &bits;
   data[2].iov_len = sizeof (bits);

   // Write all of those to the socket.
   writev (fd, &data, sizeof (data) / sizeof (data[0]));
}
在接收端,您可以读取size_t字节的第一个大小,从网络转换为主机字节顺序,转换为size_t。这会告诉你绳子的长度。然后读取该长度的缓冲区-这将是您的字符串。最后,读取另一个大小的int字节-这将是您的位字段

另见:


正如其他人指出的那样,这取决于协议。我会用这样的方法:

int sendToServer(char* msg, int bitfields)
{
   unsigned int bits = bswap32 (bitfields); // Convert host to network byte order.

   size_t len = strlen (msg);   // Calculate string length.
   size_t nlen = bswap64 (len); // Convert length's byte order from host to network.

   iovec data[3]; // Prepare 3 I/O buffers to send data by performing a single system call (they are expensive).

   // Send length of the string first.
   data[0].iov_base = &nlen;
   data[0].iov_len = sizeof (nlen);

   // Send string...
   data[1].iov_base = msg;
   data[1].iov_len = len;

   // And, of course, send bits.
   data[2].iov_base = &bits;
   data[2].iov_len = sizeof (bits);

   // Write all of those to the socket.
   writev (fd, &data, sizeof (data) / sizeof (data[0]));
}
在接收端,您可以读取size_t字节的第一个大小,从网络转换为主机字节顺序,转换为size_t。这会告诉你绳子的长度。然后读取该长度的缓冲区-这将是您的字符串。最后,读取另一个大小的int字节-这将是您的位字段

另见:


我只有不到8面旗帜。那么我如何从消息中读取标志呢?@Luke:recv进入一个无符号字符的缓冲区并提取第一个元素;这是你的旗帜。当然,确保客户端和服务器共享一个声明标志的头文件。我的标志少于8个。那么我如何从消息中读取标志呢?@Luke:recv进入一个无符号字符的缓冲区并提取第一个元素;这是你的旗帜。确保客户机和服务器共享一个声明标志的头文件,当然,-1用于确保客户机和服务器部分的大小和endianness相同。当客户端或服务器必须移植到新平台时,这会导致灾难。-1用于确保客户端和服务器部分的大小和端度相同。当客户端或服务器必须移植到新平台时,这会导致灾难。散布/聚集?你不认为这有点过分设计了答案吗?+1对于writev来说,这实际上是一个比我更干净的解决方案。这个方法对我来说是新的。我要试一试,看看能不能让它工作。只是为了确保,我是否使用ntohl将网络字节顺序转换为主机字节顺序?好的,所以我试图让服务器回显我收到的消息,但我认为我可能读错了消息,因为我在消息末尾得到的是随机符号,而不是最后几个字符。我将把我的代码添加到主帖子中。@Luke:我使用bswap,它在类Unix系统上可用。ntohl的问题在于它不支持64位数据类型,如x86_64体系结构上的大小。我确信对于类似Windows的平台,有一些替代方案。分散/聚集?你不认为这有点过分设计了答案吗?+1对于writev来说,这实际上是一个比我更干净的解决方案。嗯,这
他的方法对我来说是新的。我要试一试,看看能不能让它工作。只是为了确保,我是否使用ntohl将网络字节顺序转换为主机字节顺序?好的,所以我试图让服务器回显我收到的消息,但我认为我可能读错了消息,因为我在消息末尾得到的是随机符号,而不是最后几个字符。我将把我的代码添加到主帖子中。@Luke:我使用bswap,它在类Unix系统上可用。ntohl的问题在于它不支持64位数据类型,如x86_64体系结构上的大小。我相信对于类似Windows的平台,有一些替代方法。Re:Edits 1和2:您正在覆盖缓冲区,因此您只会将字符串回显到客户端-减去长度和标志。客户机如何知道字符串有多大?这可能不是您的问题,但没有帮助。问题似乎是服务器读取缓冲区。如果我在消息发送之前打印它,它的结尾仍然有相同的ascii字符。另外,我刚刚注意到,flag的值为-926448449,尽管我只发送了1 | 2。这似乎有点奇怪。如果你不明白,也许值得把它作为第二个问题发布。您没有太多的代码要发布,因此应该很容易理解。Re:Edits 1和2:您不需要覆盖缓冲区,因此您只需将字符串回显到客户端-减去长度和标志。客户机如何知道字符串有多大?这可能不是您的问题,但没有帮助。问题似乎是服务器读取缓冲区。如果我在消息发送之前打印它,它的结尾仍然有相同的ascii字符。另外,我刚刚注意到,flag的值为-926448449,尽管我只发送了1 | 2。这似乎有点奇怪。如果你不明白,也许值得把它作为第二个问题发布。你没有太多的代码可以发布,所以应该很容易理解。