sock通信--数据结构的传送

新版下载频道上线初期常见问题解答!!                bShare分享,迅速提升10倍流量

sock通信--数据结构的传送

分类: Linux程序设计(C/C++) 164人阅读 评论(2) 收藏 举报

  sock通信中有几个问题必须注意,由于标准的不统一,有的机器使用的大端存储,而有的机器使用的是小端存储(如果对大小端不了解可以上网搜寻一下相关信息). 我们的机器的存储方式各不相同,但是由于历史原因,网络字节序使用的是大端,也就是说,我们要通过网络传输信息到远断,我们要当心了.

  如果明确了传送信息的双方都是相同的存储方式那么还好办,如果传送双方的存储方式不相同或者不一定相同,我们就必须把发送的数据进行相应的格式转换再发送到网络上,直至远端.

  由于网络字节序是大端,那么,我们再发送一个数据结构时,需要把这个结构中的每个成员转换成网络字节序,再发送到远端,而不只是简单的发送这些数据给远端.

  下面是我在发送数据结构时使用的一些例程,希望对涉及到这方面的朋友有帮助.

  在这个例子中,我定义了一个这样的结构体进行传送


typedef struct
{
    uint16_t packetlen;
    uint8_t cmdtype;
    uint16_t sessionid;
    uint16_t messageid;
    uint32_t ackinfo;
} ControlHeader;


  定义了这些函数处理结构体中的成员,把他们转换成相应的格式存入缓存中
//
//basic convert funtion declaration
//
void SendUint32_tToBuff(char *buf, uint32_t n);
void SendUint16_tToBuff(char *buf, uint16_t n);
void SendStringToBuff(char *buf, char *str);
uint32_t GetUint32_tFromBuff(char *buf);
uint16_t GetUint16_tFromBuff(char *buf);

//
//structure convert function declaration
//
void init_ControlHeader(uint8_t type, uint16_t sid, uint16_t mid,
uint32_t ack, ControlHeader *pHead);
void sendHeadtobuff(char *buf, ControlHeader *pHead);
void getHeaderfrombuff(void *buff, ControlHeader *p);
int getHeadlen();

  上述定义存放在struct.h文件中,另外写了一个struct.c对上述声明进行定义

  1. #include "struct.h"   
  2. #include <stdio.h>   
  3. #include <strings.h>   
  4.   
  5. //#define TEST 1    
  6. //   
  7. //basic convert funciton definition   
  8. //   
  9. void SendUint32_tToBuff(char *buf, uint32_t n)  
  10. {  
  11.     n = htonl(n);  
  12.     bcopy((char *)&n, buf, sizeof(uint32_t));  
  13. }  
  14. void SendUint16_tToBuff(char *buf, uint16_t n)  
  15. {  
  16.     n = htons(n);  
  17.     bcopy((char *)&n, buf, sizeof(uint16_t));  
  18. }  
  19. uint32_t GetUint32_tFromBuff(char *buf)  
  20. {  
  21.     uint32_t n;  
  22.     bcopy(buf, (void *)&n, sizeof(uint32_t));  
  23.     n = ntohl(n);  
  24.     return n;  
  25. }  
  26. uint16_t GetUint16_tFromBuff(char *buf)  
  27. {  
  28.     uint16_t n;  
  29.     bcopy(buf, (void *)&n, sizeof(uint16_t));  
  30.     n = ntohs(n);  
  31.     return n;  
  32. }  
  33. //   
  34. //structure convert function declaration   
  35. //   
  36. void init_ControlHeader(uint8_t type, uint16_t sid, uint16_t mid,  
  37. uint32_t ack, ControlHeader *pHead)  
  38. {  
  39.     pHead->cmdtype = type;  
  40.     pHead->sessionid = sid;  
  41.     pHead->messageid = mid;  
  42.     pHead->ackinfo = ack;  
  43. }  
  44. int getHeadlen()  
  45. {  
  46.     return (sizeof(uint16_t)+sizeof(uint8_t)+sizeof(uint16_t)  
  47. +sizeof(uint16_t)+sizeof(uint32_t));  
  48. }  
  49. void sendHeadtobuff(char *buf, ControlHeader *pHead)  
  50. {  
  51.     char *pos = buf;  
  52.       
  53.     if(buf == NULL)  
  54.         fprintf(stderr, "encouter NULL pointer in sendheadertobuff/n");  
  55.     else  
  56.     {  
  57.         SendUint16_tToBuff(pos, pHead->packetlen);  
  58.         pos += sizeof(uint16_t);  
  59.         *pos = pHead->cmdtype;  
  60.         pos++;  
  61.         SendUint16_tToBuff(pos, pHead->sessionid);  
  62.         pos += sizeof(uint16_t);  
  63.         SendUint16_tToBuff(pos, pHead->messageid);  
  64.         pos += sizeof(uint16_t);  
  65.         SendUint32_tToBuff(pos, pHead->ackinfo);          
  66.     }  
  67. }  
  68. void getHeaderfrombuff(void *pbuff, ControlHeader *p)  
  69. {  
  70.     char *buf = (void *)pbuff;  
  71.     bcopy(buf, (void *)&p->packetlen, sizeof(uint16_t));  
  72.     p->packetlen = ntohs(p->packetlen);  
  73.     buf += sizeof(uint16_t);  
  74.       
  75.     p->cmdtype = *buf;  
  76.     buf += 1;  
  77.       
  78.     bcopy(buf, (void *)&p->sessionid, sizeof(uint16_t));  
  79.     p->sessionid = ntohs(p->sessionid);  
  80.     buf += sizeof(uint16_t);  
  81.       
  82.     bcopy(buf, (void *)&p->messageid, sizeof(uint16_t));  
  83.     p->messageid = ntohs(p->messageid);  
  84.     buf += sizeof(uint16_t);  
  85.       
  86.     bcopy(buf, (void *)&p->ackinfo, sizeof(uint32_t));  
  87.     p->ackinfo = ntohl(p->ackinfo);  
  88. }  
  89. #ifdef TEST   
  90. int main(int argc, char **argv)  
  91. {  
  92.     ControlHeader myheader;  
  93.     ControlHeader myh;  
  94.     uint8_t type = 1;  
  95.     uint16_t len = 2, sid = 3, mid = 4;  
  96.     uint32_t ackif = 5;  
  97.     char buf[128];  
  98.     int length = getHeadlen();  
  99.       
  100.     init_ControlHeader(type, sid, mid, ackif, &myheader);  
  101.     //see whether init_ControlHeader function right   
  102.     printf("myheader.cmdtype = %d/n", myheader.cmdtype);  
  103.       
  104.     SendUint32_tToBuff(buf, ackif);  
  105.     //see whether SendUint32_tToBuff function right   
  106.     printf("getuint32_tfrombuff : %d/n", GetUint32_tFromBuff(buf));  
  107.     SendUint16_tToBuff(buf, len);  
  108.     //see whether SendUint32_tToBuff function right   
  109.     printf("getuint16_tfrombuff : %d/n", GetUint16_tFromBuff(buf));  
  110.       
  111.     printf("header length is %d/n", length);  
  112.     sendHeadtobuff(buf, &myheader);  
  113.     //buf[length] = 0;   
  114.     printf("buf is %s/n", buf);  
  115.       
  116.     getHeaderfrombuff(buf, &myh);  
  117.     printf("myh.cmdtype = %d/n", myh.cmdtype);   
  118. }  
  119. #endif  
 

  下面我们写一个简单的网络通信例程,进行试验

  服务器端

  1. #include "unp.h"   
  2. #include <signal.h>   
  3. #include "struct.h"   
  4. #define SRV_PORT 5000   
  5. ControlHeader ch;  
  6. void sig_child(int signo)  
  7. {  
  8.     pid_t pid;  
  9.     int stat;  
  10.       
  11.     pid=wait(&stat);  
  12.     printf("child %d terminated/n",pid);  
  13.     return ;  
  14. }  
  15. void str_echo(int sockfd)  
  16. {  
  17.     char buf[1024];  
  18.     ssize_t n;  
  19.     n=Read(sockfd,buf,MAXLINE);  
  20.     if(n == 0)  
  21.         return ;  
  22.     //printf("bus is : %s/n", buf);   
  23.       
  24.     getHeaderfrombuff(buf, &ch);  
  25.     printf("ch.cmdtype = %d/n", ch.cmdtype);  
  26. }  
  27. int main(int argc,char **argv)  
  28. {  
  29.     int listenfd,connfd;  
  30.     pid_t childpit;  
  31.     socklen_t socklen;  
  32.     struct sockaddr_in cli_addr,srv_addr;  
  33.       
  34.     listenfd=Socket(AF_INET,SOCK_STREAM,0);  
  35.       
  36.     bzero(&srv_addr,sizeof(srv_addr));  
  37.     srv_addr.sin_family=AF_INET;  
  38.     srv_addr.sin_port=htons(SRV_PORT);  
  39.     srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);  
  40.       
  41.     Bind(listenfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));  
  42.       
  43.     Listen(listenfd,LISTENQ);  
  44.     if(signal(SIGCHLD,sig_child)==SIG_ERR)  
  45.     err_sys("signal");  
  46.     /* 
  47.     for(;;) 
  48.     { 
  49.     socklen=sizeof(cli_addr); 
  50.     connfd=Accept(listenfd,(struct sockaddr *)&cli_addr,&socklen); 
  51.     if((childpit=fork())==0) 
  52.     { 
  53.         Close(listenfd); 
  54.         str_echo(connfd); 
  55.         exit(0); 
  56.         } 
  57.     Close(connfd); 
  58.     }*/  
  59.     socklen=sizeof(cli_addr);  
  60.     connfd=Accept(listenfd,(struct sockaddr *)&cli_addr,&socklen);  
  61.     str_echo(connfd);  
  62.       
  63.     exit(0);  
  64. }  

客户端

  1. #include "unp.h"   
  2. #include "struct.h"   
  3. #define SRV_PORT 5000   
  4. ControlHeader ch;  
  5. void str_cli(int sockfd)  
  6. {  
  7.     ControlHeader ano;  
  8.     ssize_t n;  
  9.     uint8_t type = 1;  
  10.     uint16_t sid = 2;  
  11.     uint16_t mid = 3;  
  12.     uint32_t ack = 4;  
  13.     init_ControlHeader(type, sid, mid, ack, &ch);  
  14.     printf("ch.type = %d", ch.cmdtype);  
  15.     char buf[1024];  
  16.     sendHeadtobuff(buf, &ch);  
  17.       
  18.     getHeaderfrombuff(buf, &ano);  
  19.     printf("ano.cmdtype = %d/n", ano.cmdtype);  
  20.     //fgets(buf, 1024, stdin);   
  21.     n = Write(sockfd, buf, getHeadlen());  
  22.     if(n == 0)  
  23.     {  
  24.         fprintf(stderr, "write size : 0/n");  
  25.         return ;  
  26.     }  
  27.       
  28.       
  29. }  
  30. int main(int argc,char **argv)  
  31. {  
  32.     int sockfd;  
  33.     struct sockaddr_in srv_addr;  
  34.     if(argc!=2)  
  35.     {  
  36.         fprintf(stderr,"usage : a.out IPaddress/n");  
  37.         exit(1);  
  38.     }  
  39.     sockfd=Socket(AF_INET,SOCK_STREAM,0);  
  40.     bzero(&srv_addr,sizeof(srv_addr));  
  41.     srv_addr.sin_family=AF_INET;  
  42.     srv_addr.sin_port=htons(SRV_PORT);  
  43.     inet_pton(AF_INET,argv[1],&srv_addr.sin_addr);  //remember this   
  44.     Connect(sockfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));  
  45.     str_cli(sockfd);  
  46.     exit(0);  
  47. }  

完毕.

原文地址:https://www.cnblogs.com/moonvan/p/2174458.html