通过TCP套接字发送C结构

时间:2015-10-14 00:09:21

标签: c sockets pointers struct network-programming

我看到很多与我的问题相关的答案,但我真的不能在我的条件下使用它。

我正在使用Linux域下的C语言进行套接字编程来构建网络模块。 我必须实现一个函数,它可以发送一个由int,char,char *和一些其他结构(嵌套结构)组成的结构。

struct EnQuery
{
   char  type[6]; // insert, select , update , delete
   char * columns; //note here, it's an array of big, {name, age, sex, position, email}  not in string
   struct Values * values; //an array of values(another struct), {tom, 23, male, student, tom@compan.com}  is represented by the second struct values, not in string
   struct condition * enCondition; //  array of condition,  "name=tom and age>30" is represnted by the third struct condition
   short len;
   short rn; 
};

struct Values
{
    char * doc;
    char  key[2];
    char  s;
};

struct condition
{
     short k;              
     struct condition * children;
};

以上是我要发送的结构。 我正在声明变量并使用send()函数通过套接字发送。

我如何通过套接字发送char *? 或者是否有方法可以方便地调整char数组长度?

P.S我不能使用外部库

4 个答案:

答案 0 :(得分:2)

  

我如何通过套接字发送char *?

显然,发送指针值并不是一件有用的事情,因为指针不会指向接收计算机上的任何有效内容。

因此,您必须发送它指向的数据,而不是发送指针。执行此操作的典型方法是首先发送指针指向的字节数:

uint32_t sLen = strlen(doc)+1;  // +1 because I want to send the NUL byte also
uint32_t bigEndianSLen = htonl(sLen);
if (send(sock, &bigEndianSLen, sizeof(bigEndianSLen), 0) != sizeof(bigEndianSLen)) perror("send(1)");

....然后发送字符串的字节:

if (send(sock, doc, sLen, 0) != sLen) perror("send(2)");

在接收方,你做相反的事情:首先收到字符串的长度:

uint32_t bigEndianSLen;
if (recv(sock, &bigEndianSLen, sizeof(bigEndianSLen), 0) != sizeof(bigEndianSLen)) perror("recv(1)");
uint32_t sLen = ntohl(bigEndianSLen);

...然后接收字符串的数据:

char * doc = malloc(sLen+1);
if (recv(sock, doc, sLen, 0) != sLen) perror("recv(2)");
doc[sLen] = '\0';  // paranoia:  make sure the string is terminated no matter what

请注意,此示例代码有点天真,因为它不能正确处理send()或recv()返回传递给它们的字节数以外的值的情况。生产质量代码将正确处理错误(例如,通过关闭连接),并且还将正确处理send()或recv()发送/接收仅传输了一些所请求的字节的情况(通过调用send()/ recv()稍后再次用于剩余的未发送/未接收的字节。)

答案 1 :(得分:2)

您需要做出选择:使用“pack”函数序列化发送端内存中的数据结构,通过线路发送并使用解包函数(直接)反序列化,或者直接动态序列化/反序列化socket(最好在第一个版本的优化之后完成)。

您可以从这个开源代码中获得一些灵感,例如: https://code.google.com/p/protobuf-c/

答案 2 :(得分:0)

使用“类型编号”定义枚举。使用您的示例:

Tchar
Tstring
Tshort
Tint
TEnQuery
TValues
Tcondition
Tpop

定义一些得到或类型的标志位:

Tarray -- array of base type
现在输出类型编号。跟随实际数据。例如,输出一个Values结构:
Tvalues
Tstring,data for doc (inc EOS)
Tchar | Tarray,2,key data
Tchar,s value
Tpop
任何聚合(例如struct)都会执行与Tpop配对的隐含“Tpush”

现在您有一个字节流,您可以使用各种状态机递归处理。您需要递归函数来导出/导入所有上述类型。在导入时,关键是类型编号是您在

上发送的内容

答案 3 :(得分:-3)

结构是(ANSI) C language可用的数据类型。我相信您正在寻找以下函数来执行结构中的数据发送。

  1. socket()
  2. read()
  3. write()
  4. 请注意,这些是IPC(也称为signals),TCP/IP和/或UDP通讯的最低要求。

    对于客户端/服务器架构的简单实现(虽然这些天彻底过时)参考; client / server。您可以更好地将研究重点放在peer to peer通信上,为您提供更强大的故障转移集,因为每个对等方都保存彼此的连接信息;看到这里:

    peer to peer