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对上述声明进行定义
- #include "struct.h"
- #include <stdio.h>
- #include <strings.h>
- //#define TEST 1
- //
- //basic convert funciton definition
- //
- void SendUint32_tToBuff(char *buf, uint32_t n)
- {
- n = htonl(n);
- bcopy((char *)&n, buf, sizeof(uint32_t));
- }
- void SendUint16_tToBuff(char *buf, uint16_t n)
- {
- n = htons(n);
- bcopy((char *)&n, buf, sizeof(uint16_t));
- }
- uint32_t GetUint32_tFromBuff(char *buf)
- {
- uint32_t n;
- bcopy(buf, (void *)&n, sizeof(uint32_t));
- n = ntohl(n);
- return n;
- }
- uint16_t GetUint16_tFromBuff(char *buf)
- {
- uint16_t n;
- bcopy(buf, (void *)&n, sizeof(uint16_t));
- n = ntohs(n);
- return n;
- }
- //
- //structure convert function declaration
- //
- void init_ControlHeader(uint8_t type, uint16_t sid, uint16_t mid,
- uint32_t ack, ControlHeader *pHead)
- {
- pHead->cmdtype = type;
- pHead->sessionid = sid;
- pHead->messageid = mid;
- pHead->ackinfo = ack;
- }
- int getHeadlen()
- {
- return (sizeof(uint16_t)+sizeof(uint8_t)+sizeof(uint16_t)
- +sizeof(uint16_t)+sizeof(uint32_t));
- }
- void sendHeadtobuff(char *buf, ControlHeader *pHead)
- {
- char *pos = buf;
- if(buf == NULL)
- fprintf(stderr, "encouter NULL pointer in sendheadertobuff/n");
- else
- {
- SendUint16_tToBuff(pos, pHead->packetlen);
- pos += sizeof(uint16_t);
- *pos = pHead->cmdtype;
- pos++;
- SendUint16_tToBuff(pos, pHead->sessionid);
- pos += sizeof(uint16_t);
- SendUint16_tToBuff(pos, pHead->messageid);
- pos += sizeof(uint16_t);
- SendUint32_tToBuff(pos, pHead->ackinfo);
- }
- }
- void getHeaderfrombuff(void *pbuff, ControlHeader *p)
- {
- char *buf = (void *)pbuff;
- bcopy(buf, (void *)&p->packetlen, sizeof(uint16_t));
- p->packetlen = ntohs(p->packetlen);
- buf += sizeof(uint16_t);
- p->cmdtype = *buf;
- buf += 1;
- bcopy(buf, (void *)&p->sessionid, sizeof(uint16_t));
- p->sessionid = ntohs(p->sessionid);
- buf += sizeof(uint16_t);
- bcopy(buf, (void *)&p->messageid, sizeof(uint16_t));
- p->messageid = ntohs(p->messageid);
- buf += sizeof(uint16_t);
- bcopy(buf, (void *)&p->ackinfo, sizeof(uint32_t));
- p->ackinfo = ntohl(p->ackinfo);
- }
- #ifdef TEST
- int main(int argc, char **argv)
- {
- ControlHeader myheader;
- ControlHeader myh;
- uint8_t type = 1;
- uint16_t len = 2, sid = 3, mid = 4;
- uint32_t ackif = 5;
- char buf[128];
- int length = getHeadlen();
- init_ControlHeader(type, sid, mid, ackif, &myheader);
- //see whether init_ControlHeader function right
- printf("myheader.cmdtype = %d/n", myheader.cmdtype);
- SendUint32_tToBuff(buf, ackif);
- //see whether SendUint32_tToBuff function right
- printf("getuint32_tfrombuff : %d/n", GetUint32_tFromBuff(buf));
- SendUint16_tToBuff(buf, len);
- //see whether SendUint32_tToBuff function right
- printf("getuint16_tfrombuff : %d/n", GetUint16_tFromBuff(buf));
- printf("header length is %d/n", length);
- sendHeadtobuff(buf, &myheader);
- //buf[length] = 0;
- printf("buf is %s/n", buf);
- getHeaderfrombuff(buf, &myh);
- printf("myh.cmdtype = %d/n", myh.cmdtype);
- }
- #endif
下面我们写一个简单的网络通信例程,进行试验
服务器端
- #include "unp.h"
- #include <signal.h>
- #include "struct.h"
- #define SRV_PORT 5000
- ControlHeader ch;
- void sig_child(int signo)
- {
- pid_t pid;
- int stat;
- pid=wait(&stat);
- printf("child %d terminated/n",pid);
- return ;
- }
- void str_echo(int sockfd)
- {
- char buf[1024];
- ssize_t n;
- n=Read(sockfd,buf,MAXLINE);
- if(n == 0)
- return ;
- //printf("bus is : %s/n", buf);
- getHeaderfrombuff(buf, &ch);
- printf("ch.cmdtype = %d/n", ch.cmdtype);
- }
- int main(int argc,char **argv)
- {
- int listenfd,connfd;
- pid_t childpit;
- socklen_t socklen;
- struct sockaddr_in cli_addr,srv_addr;
- listenfd=Socket(AF_INET,SOCK_STREAM,0);
- bzero(&srv_addr,sizeof(srv_addr));
- srv_addr.sin_family=AF_INET;
- srv_addr.sin_port=htons(SRV_PORT);
- srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
- Bind(listenfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));
- Listen(listenfd,LISTENQ);
- if(signal(SIGCHLD,sig_child)==SIG_ERR)
- err_sys("signal");
- /*
- for(;;)
- {
- socklen=sizeof(cli_addr);
- connfd=Accept(listenfd,(struct sockaddr *)&cli_addr,&socklen);
- if((childpit=fork())==0)
- {
- Close(listenfd);
- str_echo(connfd);
- exit(0);
- }
- Close(connfd);
- }*/
- socklen=sizeof(cli_addr);
- connfd=Accept(listenfd,(struct sockaddr *)&cli_addr,&socklen);
- str_echo(connfd);
- exit(0);
- }
客户端
- #include "unp.h"
- #include "struct.h"
- #define SRV_PORT 5000
- ControlHeader ch;
- void str_cli(int sockfd)
- {
- ControlHeader ano;
- ssize_t n;
- uint8_t type = 1;
- uint16_t sid = 2;
- uint16_t mid = 3;
- uint32_t ack = 4;
- init_ControlHeader(type, sid, mid, ack, &ch);
- printf("ch.type = %d", ch.cmdtype);
- char buf[1024];
- sendHeadtobuff(buf, &ch);
- getHeaderfrombuff(buf, &ano);
- printf("ano.cmdtype = %d/n", ano.cmdtype);
- //fgets(buf, 1024, stdin);
- n = Write(sockfd, buf, getHeadlen());
- if(n == 0)
- {
- fprintf(stderr, "write size : 0/n");
- return ;
- }
- }
- int main(int argc,char **argv)
- {
- int sockfd;
- struct sockaddr_in srv_addr;
- if(argc!=2)
- {
- fprintf(stderr,"usage : a.out IPaddress/n");
- exit(1);
- }
- sockfd=Socket(AF_INET,SOCK_STREAM,0);
- bzero(&srv_addr,sizeof(srv_addr));
- srv_addr.sin_family=AF_INET;
- srv_addr.sin_port=htons(SRV_PORT);
- inet_pton(AF_INET,argv[1],&srv_addr.sin_addr); //remember this
- Connect(sockfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));
- str_cli(sockfd);
- exit(0);
- }
完毕.