天天看點

sock通信--資料結構的傳送

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

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

SendUint16_tToBuff(pos, pHead->messageid);

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

bcopy(buf, (void *)&p->messageid, sizeof(uint16_t));

p->messageid = ntohs(p->messageid);

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

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

用戶端

void str_cli(int sockfd)

ControlHeader ano;

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

sendHeadtobuff(buf, &ch);

getHeaderfrombuff(buf, &ano);

printf("ano.cmdtype = %d/n", ano.cmdtype);

//fgets(buf, 1024, stdin);

n = Write(sockfd, buf, getHeadlen());

fprintf(stderr, "write size : 0/n");

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

inet_pton(AF_INET,argv[1],&srv_addr.sin_addr); //remember this

Connect(sockfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));

str_cli(sockfd);

下一篇: Python 推導式

繼續閱讀