套接字编程基础

网络编程,从某种程度上说就是进程间通信,套接口类似于进程的ID,通过IP地址指定通信的主机,通过端口号指定和主机上的那个进程通信,也就是通过IP+端口号唯一确定了通信的进程。
通用套接口结构
结构:
struct sockaddr{
       uint8_t sa_len;//数据长度
       sa_family sa_family;//协议名
       char sa_data[14];//14位的协议地址
}
头文件:sys/socket.h
说明:通用套接字接口结构

Posix.lg中数据类型
数据类型           说明                   头文件
int8_t         带符号的8位整数       sys/types.h
uint8_t       无符号的8位整数       sys/types.h
int16_t       带符号的16位整数     sys/types.h
uint16_t     无符号的16位整数     sys/types.h
int32_t       带符号的32位整数     sys/types.h
uint32_t     无符号的32位整数     sys/types.h
sa_family_t 套接口地址结构的地址簇                     sys/socket.h
socklen_t    套接口地址的长度,一般为uint32_t     sys/socket.h
in_port_t    TCP或UDP端口,一般为uint16_t         netinet/in.h
in_addr_t    Ipv4地址,一般为uint32_t                 netinet/in.h

IPv4套接口地址数据结构
结构:
    struct sockaddr_in {
     short int sin_family; //IPV4协议为AF_INET
     unsigned short int sin_port;//16位端口号,网络字节序列
     struct in_addr sin_addr; //
unsigned char sin_zero[8]; //备用域,为了和struct sockaddr字
//节数保持相同;
  };
    struct in_addr{
       in_addr_t s_addr;//32位IP地址,网络字节序列
} ;
头文件:neitnet/in.h
说明:略
常用函数
字节排序函数
计算机内存中有两种数据存储方式,一种为小端字节序,也就是低地址存储数据低字节,高地址存储数据高字节;一种为大端字节序,也就是低地址存储高字节,高地址存储低字节。网络字节序采用大端字节序,而主机字节序有可能为小端字节序,因此,存在着字节序的转换问题。
函数:
uint16_t htons(uint16_t hostvalue);
uint32_t htonl(uint32_t hostvalue);
uint16_t ntohs(uint16_t netvalue);
uint32_t ntohl(uint32_t netvalue);
头文件:netinet/in.h
说明:函数中h表示host,n表示network,s表示short,l表示long,一般而言,使用htonshentohs转换端口号,htonl和ntohl转换IP地址。
字节操作函数
字节操作函数主要是用于读取结构体中的某几个字节。
函数:
    void bzero(void *dest,size_t nbytes);
    void bcopy(const void *src,void *dest,size_t nbytes);
    int bcmp(const void *prt1,const void *ptr2,size_t nbytes);
    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);
头文件:string.h
说明:以b打头的函数为支持套接口函数的系统所提供,mem为支持ANSI C库提供的函数;其中,bzero将制定的起始地址设置为0(nbytes表示字长),bcopy和memcpy为复制,bcmp和memcmp为比较,memset将目标中指定数据的字节设置为指定的值。
地址转换函数
在TCP/IP的网络上,使用ASCII地址,也就是使用“.”隔开的4个十进制数表示,但在套接字中使用32位网络字节序,因此必须进行地址转换。
函数: in_addr_t inet_addr(const char *straddr);
       int inet_aton(const char* straddr,struct in_addr *addrp);
       char* inet_ntoa(struct in_addr inaddr);
头文件:sys/socket.h netinet/in.h arpa/inet.h
说明:
inet_addr成功返回32位网络字节序地址,出错返回INADDR_NONE。INADDR_NONE为linux定义的一个常数,是一个不存在的ip地址;
inet_aton将ASCII转换成网络字节序的32位二进制值,输入的ASCII放在straddr中,转换后放在addrp中,成功返回1,失败返回0;
   inet_ntoa将32位二进制地址转换成ASCII地址,成功返回ASCII值,失败返回NULL。
字节流读取函数
         仍然为read和write函数,和文件I/O不同在于其读取的字节数可能比要求的少,但不是读取错误。
创建套接口函数
函数:int socket(int family,int type,int protocol);
头文件:sys/socket.h
说明:创建一个套接口描述字,也就是套接字,返回值大于等于0,表示成功,否则表示失败,protocol一般为0,其中family的取值如下:
AF_LOCAL  UNIX协议簇       AF_ROUTE  路由套接口
AF_INET   IPv4协议         AF_INET6  IPv6协议
AF_KEY    密钥套接口
type的取值如下:
    SOCK_STREAM  TCP套接口            SOCK_DGRAM      UDP套接口
    SOCK_PACKET  支持数据链路访问     SOCK_RAW     原始套接口
套接口绑定函数
函数:int bind(int sockd,const struct sockaddr *myaddr,socklen_t addrlen)
头文件:sys/socket.h
说明:成功返回值为0,失败返回-1,并设置errno值。该函数的调用不是必须的,只有需要和固定的某个特定网络地址和端口通信时才会使用到,一般而言调用connect和listen函数时,linux内核会自动分配一个地址和端口号。该函数的调用,对于服务器端而言,myaddr必须为从该地址接受客户信息的地址,对于客户端而言,myaddr指定了套接口的源地址。对于端口号,可以任意指定,但是不能为系统保留端口。此外,bind允许内核指定地址,当套接口设定port为0时,表示有内核指定端口号,设置sin_addr为INADDR_ANY时,有内核指定IP地址,
套接口链接函数(客户端使用)
函数:int connect(int sockfd,const struct sockaddr *myaddr,socklen_t addrlen)
头文件:sys/socket.h    sys/types.h
说明:链接成功返回0,失败返回-1,并设置errno的值
套接口监听函数(服务器端使用)
函数:(1)int listen(int sockfd,int backlog);
      (2)int accept(int sockfd,const struct sockaddr *myaddr,socklen_t *addrlen)
头文件:sys/socket.h
说明:
listen用来监听,其中backlog表示内核为此套接口设定的接受客户端请求的最大连接数。成功返回0,失败返回-1,并设置errno的值。
accept主要用来处理各个连接,其功能为从已经完成的来你接队列的队头返回下一个已完成连接,如果已完成连接队列为空,则进程休眠。返回非负描述字表示成功,出错返回-1。成功时,返回值用来标识新建立的链接。其与参数sockfd的区别在于,监听套接口描述字只有一个,而且一直存在,而函数返回值表示已连接的套接口描述字,当连接断开时就关闭该描述字,如果不需要客户端的地址和端口信息,可以将第二个和第三个参数设置为空指针。
获取本地或远程协议地址
函数:
(1) getsockname(int sockfd,struct sockaddr *localaddr,socklen_t *addrlen);
(2) getpeername(int sockfd,struct sockaddr *peeraddr,socklen_t *addrlen);
头文件:sys/socket.h
说明:(1)返回本地协议地址,(2)返回远程协议地址
当不调用bind或调用bind没有指定本地IP地址和端口时,可以调用函数getsockname来返回内核分配的本地IP地址和端口号,还可以获取到套接口的协议簇。当一个新的连接建立时,服务器端也可以调用getsockname来获取分配给此连接的本地IP地址;当服务器端的一个子进程调用函数exec启动执行时,只能调用getpeername来获取客户端IP地址和端口号。
名字地址转换成数字地址
函数:struct hostent *gethostbyname(const char *hastname);
头文件:netdb.h
说明:函数返回成功返回hostent指针,失败返回空指针,并设置h_errno的值。其中hostent的结构如下:
struct hostent{
       char *h_name;//主机的规范化名字;
       char **h_aliases;//足迹的别名列表;
       char h_addrtype;//返回主机地址类型(ipv4,ipv6)
       char h_length;//返回地址长度(以字节为单位)
char **h_addr_list;// 主机的一组网络地址列表,使用网络字节序
};
数字地址转化成名字地址
函数:struct hostent *gethostbyaddr(const void *addr,socklet_t len,int type);
头文件:netdb.h
说明:addr为一个含有地址结构(in_addr或in_addr6)的指针,len为该结构的大小,IPV4为4,IPV6为6,type为协议簇。
获取当前主机名字
函数:uname(struct utsname *name);
头文件:sys/utsname.h
说明:返回当前主机的名字,常和gethostbyname一起使用来确定本地主机的IP地址。返回值大于等于0为成功,如果为-1表示失败。Struct ustname结构如下:
struct utsname{
       char sysname[];
       char nodename[];
        char release[];
       char version[];
       char machine[];
       #ifdef  _GUN_SOURCE
       char domainname[];
    #endif
};
服务器名转换成端口号
函数:struct servent *getservbyname(const char *name,const char *proto);
头文件:netdb.h
说明:实现将服务器名转换成端口号的功能,返回非空指针表示成功,否则为失败,serv为服务器名,proto为协议名,可以为空,其中servent定义如下:
struct servent{
    char *s_name;//规范服务器名
    char *s_aliases;//别名成员列表
    int s_port;//端口号
    char *s_proto;//函数调用时指定的协议名
}
端口号转换成服务器名
函数:struct servant *getservbyport(int port,const char* proto);
头文件:netdb.h
说明:实现从端口号到服务器名的转换,返回结果为空指针表示成功,否则失败,port为网络字节序,proto为协议名。


原文: http://blog.csdn.net/xiaoweibeibei/article/details/6584250

你可能感兴趣的:(套接字)