读pdcp_lte_logger.c代码学会的新知识


1. sockaddr_in , sockaddr , in_addr区别

整理自http://blog.csdn.net/jackychu/article/details/4461927
另一篇相关文章以备参考:struct sockaddr与struct sockaddr_in的区别和联系

1.1 sockaddr:通用的socket地址

struct sockaddr {
    unsigned   short   sa_family;     
    char   sa_data[14];     
};  

1.2 sockaddr_in:Internet socket

sockaddr和sockaddr_in可以进行类型转换

struct sockaddr_in {  
    short   int   sin_family;     
    unsigned   short   int   sin_port;     
    struct   in_addr   sin_addr;     
    unsigned   char   sin_zero[8];     
};

1.3 in_addr:32位IP地址。

struct   in_addr   {  
    union {
        struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
        struct { u_short s_w1,s_w2; } S_un_w;
        u_long S_addr; 
    } S_un;
    #define s_addr  S_un.S_addr
};

inet_addr()是将一个点分制的IP地址(如192.168.0.1)转换为上述结构中需要的32位IP地址(0xC0A80001)。

1.4 用法

填值的时候使用sockaddr_in结构,而作为函数(如socket, listen, bind等)的参数传入的时候转换成sockaddr结构就行了,毕竟都是16个字符长。

通常的用法是:

int   sockfd;  
struct   sockaddr_in   my_addr;  
sockfd   =   socket(AF_INET,   SOCK_STREAM,   0);     
   
my_addr.sin_family   =   AF_INET;     
my_addr.sin_port   =   htons(MYPORT);     
my_addr.sin_addr.s_addr   =   inet_addr("192.168.0.1");  
   
bzero(&(my_addr.sin_zero),   8);     
    
bind(sockfd,   (struct   sockaddr   *)&my_addr,   sizeof(struct   sockaddr));

可以用C++做个不太准确的假设。
sockaddr是base class
sockaddr_in等是derived(派生) class
如此一来,bind, connect, sendto, recvfrom等函数就可以使用base class
来处理多种不同的derived class了。
但是实际上,这是没有继承关系数据结构(C嘛),所以需要强制造型来转换数据类型。正因为如此,在sendto的时候需要给出len长度,因为不同的sockaddr_xx实现长度并不相同。

1.5 P.S.名词解析:

  • 主机字节序:
    不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。最常见的有两种 1.Little endian:低字节存高地址,高字节存低地址 2.Big endian:低字节存低地址,高字节存高地址
  • 网络字节序:
    网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。
  • 字节序转换
    为了进行转换bsd socket提供了转换的函数,有下面四个网络与主机字节转换函数:htons ntohs htonl ntohl
    s==>short
    l==>long
    h==>host
    n==>network
  • htons:把unsigned short类型从主机序转换到网络序
  • htonl:把unsigned long类型从主机序转换到网络序
  • ntohs:把unsigned short类型从网络序转换到主机序
  • ntohl:把unsigned long类型从网络序转换到主机序

在使用little endian的系统中 这些函数会把字节序进行转换
在使用big endian类型的系统中这些函数会定义成空宏

2. gethostbyname()的返回值类型struct hostent

整理自http://blog.csdn.net/wangjie5540/article/details/23429083

2.1 hostent数据结构:

struct hostent { 
   char *h_name; 
   char **h_aliases; 
   int h_addrtype; 
   int h_length; 
   char **h_addr_list; 
}; 
#define h_addr h_addr_list[0]

这个数据结构的详细资料:
struct hostent:

  • h_name – 地址的正式名称。
  • h_aliases – 空字节-地址的预备名称的指针。
  • h_addrtype –地址类型; 通常是AF_INET。
  • h_length – 地址的比特长度。
  • h_addr_list – 零字节-主机网络地址指针。网络字节顺序。
  • h_addr - h_addr_list中的第一地址。

2.2 gethostbyname()的使用

相当简单,你只是传递一个保存机器名的字符串(例如 "whitehouse.gov") 给gethostbyname(),然后从返回的数据结构struct hostent中获取信息。

gethostbyname()成功时返回一个指向结构体hostent的指针,或者是个空(NULL) 指针。(但是和以前不同,不设置errno,h_errno设置错 误信息。请看下面的 herror()。)

如何使用呢? 这个函数可不象它看上去那么难用。
这里是个例子:

int main(int argc, char *argv[]) { 
    struct hostent *h; 
    if (argc != 2) { /* 检查命令行 */ 
        fprintf(stderr,"usage: getip address "); 
        exit(1); 
    } 
    if ((h=gethostbyname(argv[1])) == NULL) { /* 取得地址信息 */ 
        herror("gethostbyname"); 
        exit(1); 
    } 
    printf("Host name : %s ", h->h_name); 
  printf("IP Address : %s ",inet_ntoa(*((struct in_addr *)h->h_addr))); 
    return 0; 
} 

注意
在使用 gethostbyname() 的时候,你不能用perror() 打印错误信息 (因为 errno 没有使用),你应该调用 herror()。

唯一也许让人不解的是输出 IP 地址信息。h->h_addr 是一个 char *, 但是 inet_ntoa() 需要的是 struct in_addr。因此,我转换 h->h_addr 成 struct in_addr *,然后得到数据。

3. sendto():经socket传送数据

整理自http://blog.csdn.net/tdk_root/article/details/7888574

  • 相关函数
    send , sendmsg,recv , recvfrom , socket
  • 表头文件
    #include < sys/types.h >
    #include < sys/socket.h >
  • 定义函数
int sendto ( socket s , const void * msg, int len, unsigned int flags, const struct sockaddr * to , int tolen ) ;
  • 函数说明
    sendto() 用来将数据由指定的socket传给对方主机。
  • 参数们:
    s:已建好连线的socket,如果利用UDP协议则不需经过连线操作
    msg:指向欲连线的数据内容
    flags 一般设0,详细描述请参考send()。
    to:用来指定欲传送的网络地址,结构sockaddr请参考bind()。
    tolen:sockaddr的结构长度。
  • 返回值:
    成功则返回实际传送出去的字符数,失败返回-1,错误原因存于errno 中。
  • 错误代码
      EBADF 参数s非法的socket处理代码。
      EFAULT 参数中有一指针指向无法存取的内存空间。
      WNOTSOCK 参数 s为一文件描述词,非socket。
      EINTR 被信号所中断。
      EAGAIN 此动作会令进程阻断,但参数s的socket为不可阻断的。
      ENOBUFS 系统的缓冲内存不足。
      EINVAL 传给系统调用的参数不正确。
  • 范例
#include < sys/types.h >
#include < sys/socket.h >
#include <arpa.inet.h>
#define PORT 2345 /*使用的port*/
main(){
  int sockfd,len;
  struct sockaddr_in addr;
  char buffer[256];
  /*建立socket*/
  if(sockfd=socket (AF_INET,SOCK_DGRAM,0))<0){
      perror (“socket”);
      exit(1);
  }
  /*填写sockaddr_in 结构*/
  bzero ( &addr, sizeof(addr) );
  addr.sin_family=AF_INET;
  addr.sin_port=htons(PORT);
  addr.sin_addr=hton1(INADDR_ANY) ;
  if (bind(sockfd, &addr, sizeof(addr))<0){
      perror(“connect”);
      exit(1);
  }
  while(1){
      bzero(buffer,sizeof(buffer));
      len = recvfrom(socket,buffer,sizeof(buffer), 0 , &addr &addr_len);
      /*显示client端的网络地址*/
      printf(“receive from %s\n “ , inet_ntoa( addr.sin_addr));
      /*将字串返回给client端*/
      sendto(sockfd,buffer,len,0,&addr,addr_len);
  }
}

执行 请参考recvfrom()

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容

  • 研究IPv6 socket编程原因: Supporting IPv6 in iOS 9 WWDC2015苹果宣布在...
    li大鹏阅读 7,288评论 7 15
  • 网络模型 物理层 物理层表示的是比特流传输,通常包括串口/COM口、并行/LPT口、USB、网线接口、电话线接口;...
    秋风弄影阅读 703评论 0 2
  • 大纲 一.Socket简介 二.BSD Socket编程准备 1.地址 2.端口 3.网络字节序 4.半相关与全相...
    y角阅读 2,380评论 2 11
  • 什么是TCP/IP、UDP? TCP/IP(Transmission Control Protocol/Inter...
    liuboxx1阅读 981评论 0 1
  • 打仗一样的一周终于要过完了。昨天上班同事小玉儿给我们讲了自己一夜没睡。下班回家在地铁上晕倒了,醒来后发现自己躺在医...
    不一样的烟火sss阅读 116评论 0 0