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