套接字结构

套接字编程简介

最近在看《UNIX网络编程卷一》,算是写的读书笔记吧.

IPv4套接字地址结构

IPv4套接字地址结构定义在 < netinet/in.h > 头文件中.它以 sockaddr_in 命名.下面是它的结构体:

struct in_addr {
    in_addr_t       s_addr;             32位IPv4地址,网络字节序
};

struct sockaddr_in {
    uint8_t         sin_len;
    sa_family_t     sin_family;         协议类型
    in_port_t       sin_port;           端口号

    struct in_addr  sin_addr;           

    char            sin_zero[8];
}

  • 结构体中的sin_len通常是不用设置的,它存在的目的是为了简化长度可变套接字地址结构的处理.
  • sin_zero[8]总是被设置为0.按照惯例,整个结构体都会被初始化为0,所以这个未曾使用的数组一般不用特意去管它.
  • 在结构体in_addr中的in_addr_t类型一般为 uint32_t ,而 in_port_t 通常为 uint16_t .

值-结果参数

本来这一部分的内容不多,但是我觉得这是一个很好的解决小问题的思路.于是单拿出来写一写.

当往一个套接字函数传递套接字地址结构的时候,结构总是以引用(也就是指针)的形式来传递,同时参数中还会指明该结构体的
长度.但是长度的传递方式则取决于传递的方向:从进程到内核或者从内核到进程.

  • 当长度是从进程传递到内核的时候,参数是结构体的整数大小,从而使内核知道到底要从进程复制多少数据,从哪复制数据进来.

  • 从内核到进程传递套接字地址结构的时候,参数则是指向结构体大小的指针.当函数被调用的时候,它的作用是告诉内核结构体的长度,
    以免内核在写结构体时越界.当函数返回的时候,结构大小的指针又是一个结果,它告诉进程,内核在该结构体中究竟存储了多少信息.

  • 这种类型的参数成为 值-结果参数.这个参数在被调用时和返回时代表着两个不同的含义.

字节操纵函数

Berkeley函数由于兼容性的问题早已经不推荐使用了,所以我也就不再介绍了.

    void *memset (void *dest,int c,size_t len);
    void *memcpy (void *dest,const void *src,size_t nbytes);
    int memcmp(const void *ptr1,const void *ptr2,size_t nbytes);

函数名写的比较明确,这三个函数分别是memory set,memory copy以及memory compare.所以就不详细讲了.

    int inet_aton(const char *strptr,struct in_addr *addrptr);

    in_addr_t inet_addr(const char *strptr);

    char *inet_ntoa(struct in_addr inaddr);
  • inet_aton : 将字符串转换为in_addr并存入我们传入的in_addr参数.
  • inet_addr : 将字符串转化为in_addr_t(也就是in_addr结构体中的内容类型),并将其返回.
    • inet_ntoa : 将结构体in_addr转化为字符串并返回.

需要注意的是,inet_aton中的第二个参数struct in_addr可以传入空指针,此时函数只会检查字符串的有效性,不会存储结果.

I/O读写函数

字节流套接字(例如TCP套接字)上的调用read或者write函数的时候得到的字节数可能会比请求的要少,这是由于套接字缓冲区已经满了的
原因.稍后我会再推荐一篇关于套接字缓冲区的内容.

在本书中还写了三个函数用来包装read,write和readline,目的就是为了解决读出的字节与请求字节不相同的问题.其中的关键点就是通过
重复调用函数,并且对函数的返回值加以判断,如果是0或者EINTR的话就继续循环,直到读出请求的字节数为止.

posted @ 2016-10-02 16:05  XLLL  阅读(580)  评论(0编辑  收藏  举报