linux套接字编程

来源:互联网 发布:mysql mvcc 乐观锁 编辑:程序博客网 时间:2024/06/05 17:40

套接字描述符

       套接字是通信端点的抽象,和用文件描述符来访问文件同理,应用程序用套接字描述符来访问套接字,套接字在unix系统中被当做是一种文件描述符。虽然套接字本质上是一种文件描述符,但并不是完全可以当做文件描述符来操作,例如,有些以文件描述符作为参数的函数就不能接受套接字为参数。例如lseek函数就不能以套接字作为参数,因为套接字不支持文件偏移量的概念。我们可以理解套接字是一种添加了某些限制的文件描述符。
       套接字通信的本质是进程将要发送的字符写入套接字描述符所对应的文件中,然后操作系统负责传输数据,接收方从接收方的套接字描述符所对应的文件中读取传送的数据。

创建套接字
<span style="font-size:10px;font-weight: normal;">#include <sys/socket.h>int socket(int domain,int type,int protocol);</span>
   第一个参数指定套接字的通信特性,包括地址结构等,POSIX.1标准定义的域:

AF_INET       //Ipv4英特网域AF_INET6      //Ipv6英特网域AF_UNIX        //unix域AF_UPSPEC     //未指定//在有些系统中AF_UNIX用AF_LOCAL代替,它用来标示本地进程间通信//前缀为AF表示的是地址族,老一点的系统中PF标示协议族

  第二个参数指定套接字的类型常用的有TCP协议对应的有序,可靠,双向,面向连接的字节流和UDP协议对应的固定长度的,无连接的,不可靠的报文传递。

SOCK_STREAM    //TCP字节流SOCK_DGRAM     //UDP报文传递SOCK_RAW         //IP协议的数据报接口SOCK_SEQPACKET  //固定长度的,可靠地有序的数据报传输


  

  第三个参数通常为0,表示给定的域和套接字选择默认的协议,例如SOCK_STREAM对应的是TCP协议,如果选定的协议族和套接字类型有多个协议可选,可以通过该参数来指定,因特网套接字定义的协议:

<span style="font-size:10px;font-weight: normal;">IPPROTO_IP        //IPv4网际协议IPPROTO_IPV6    //IPv6网际协议IPPROTO_ICMP    //因特网控制报文协议IPPROTO_RAW     //原始IP数据包协议IPPROTO_TCP       //传输控制协议IPPROTO_UDP      //用户数据报协议</span>

字节序及转换

不同的处理器架构可能对应不同的字节序。
大端字节序:最大字节地址出现在最低有效字节上。
小端字节序:最大字接地址出现在最高有效位上。

常用的四个处理器字节序和网络字节序间的转换函数

<span style="font-size:12px;font-weight: normal;">#include <arpa/inet.h>unit32_t htonl(unit32_t hostint32) //32为整数处理器序转换为网络序unit32_t ntohl(unit32_t nettint32) //32为整数网络序转换为处理器序unit16_t htons(unit16_t hostint16) //16为整数处理器序转换为网络序unit16_t ntohs(unit16_t nettint16) //16为整数网络序转换为处理器序</span>

套接字地址结构

通用套接字(为了实现协议的无关性,在bind和connect等系统调用时,特定于某种协议的套接字结构指针都要强制转换为通用套接字指针)
struct sockaddr{      sa_family_t   sa_family;    //通信地址类型,实际上被定义为unsigned short      char sa_data[14];           //14字节的IP地址和端口信息      }
IPv4套接字
struct sockaddr_in{       unsigned short      sin_len;       //地址长度       sa_family_t         sin_family;    //通信地址类型       unsigned short int  sin_port;      //16位端口号,以网络字节序存储       struct in_addr      sin_addr;      //地址结构       in_addr结构只有一个成员 unit32_t s_addr:32位IPv4地址,网络字节序存储       unsigned char       sin_zero[8];   //未使用的字段,填充为0}
IPv6套接字
struct sockaddr_in6{       unsigned short int     sin6_len;       //地址长度       short int             sin6_family;     //通信地址类型       in_port_t             sin6_port;       //16位端口号,以网络字节序存储       uint32_t              sin6_flowinfo;   //低24位是流量标号,中间4字节的优先级标识,其他4位保留       struct in6_addr       sin6_addr;       //结构中有一个成员unsigned long s6_addr; 128位的ipv6地址}

常用的字节操作函数
#include <string.h>void bzero(void *dest, size_t nbytes);                           //内存置0void bcopy(const void *ptrl,void*dest,size_t nbytes)             //内存数据的copyint bcmp(const void *ptrl1,const void *ptrl2,size_t nbytes);     //内存数据比较,如果第一个不同的位置ptrl1大,返回大于0的数,相等返回0,小于返回小于0的值void memset(void *dest int c,size_t len);                        //给指定位数的字节设置位值int memcopy(const void *ptrl,void*dest,size_t nbytes);           //用法同上int memcmp(const void *ptrl1,const void *ptrl2,size_t nbytes);   //用法同上

整数与IP地址的转换
#include <arpa/inet.h>int inet_aton(const char *straddr,struct in_addr *addrptr);   //将点分十进制的IP地址转换为网络字节序的32位二进制char *inet_ntoa(struct in_addr);                              //将地址结构转换为点分十进制ip地址对应的串in_addr_t inet_addr(const char *straddr);                     //和inet_aton的功能相同

域名与IP地址之间的转换
#include <netdb.h>struct hostnet *gethostbyname(const char *hostname);                     //实现域名或主机名到IP地址的转换struct hostnet *gethostbuaddr(const char * addr,size_t len,int family);   //len是字符串的大小,family是协议族/结构体 struct hostent也在<netdb.h>中定义*/struct hostent{     char *h_name;             //主机的正式名称     char **h_aliases;         //主机的别名     int  h_addrtype;          //主机的地址类型     int  h_length;            //主机的地址长度     char **h_addr_list;       //主机的IP地址列表};#define h_addr h_addr_list[0];  //主机的第一个IP地址






0 0
原创粉丝点击