【网络编程】常用函数总结

套接字格式

通用套接字格式

/* POSIX.1g 规范规定了地址族为2字节的值.  */
typedef unsigned short int sa_family_t;
/* 描述通用套接字地址  */
struct sockaddr{
    sa_family_t sa_family;  /* 地址族.  16-bit*/
    char sa_data[14];   /* 具体的地址值 112-bit */
  }; 

IPv4套接字地址格式


/* IPV4套接字地址,32bit值.  */
typedef uint32_t in_addr_t;
struct in_addr
  {
    in_addr_t s_addr;
  };
  
/* 描述IPV4的套接字地址格式  */
struct sockaddr_in
  {
    sa_family_t sin_family; /* 16-bit AF_INET*/
    in_port_t sin_port;     /* 端口口  16-bit*/
    struct in_addr sin_addr;    /* Internet address. 32-bit */


    /* 这里仅仅用作占位符,不做实际用处  */
    unsigned char sin_zero[8];
  };

IPv6套接字地址格式

struct sockaddr_in6
  {
    sa_family_t sin6_family; /* 16-bit AF_INET6*/
    in_port_t sin6_port;  /* 传输端口号 # 16-bit */
    uint32_t sin6_flowinfo; /* IPv6流控信息 32-bit*/
    struct in6_addr sin6_addr;  /* IPv6地址128-bit */
    uint32_t sin6_scope_id; /* IPv6域ID 32-bit */
  };

本地套接字地址格式

struct sockaddr_un {
    unsigned short sun_family; /* 固定为 AF_LOCAL */
    char sun_path[108];   /* 路径名 */
};

常用socket API

socket创建套接字

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int socket(int domain, int type, int protocol);
/*
参数:
    domain:选择协议族PF_INET、PF_INET6 以及 PF_LOCAL 等
    type: 明确交流语义
        SOCK_STREAM: 有序,可靠基于连接的字节流;TCP
        SOCK_DGRAM:面向无连接的不可靠的数据报; UDP
        SOCK_RAW: 表示的是原始套接字。
    protocol:指定通信协议,已废弃,一般写成0 
*/
/*
返回值:
    创建成功,返回文件描述符
    失败,返回-1
*/

bind绑定套接字和套接字地址

作用:将参数sockfd和addr绑定在一起,使sockfd这个用于网络通讯的文件描述符监听addr所描述的地址和端口号。struct sockaddr *是一个通用指针类型,addr参数实际上可以接受多种协议的sockaddr结构体,而它们的长度各不相同,所以需要第三个参数addrlen指定结构体的长度。

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*
参数:
    sockfd: 待绑定的套接字,文件描述符
    addr: 套接字地址,构造出IP地址+端口号
    addrlen: 绑定的套接字地址的大小
*/
/*
返回值:
    创建成功,返回0
    失败,返回-1
*/
/*Example*/
struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr)); //将整个结构体清零
servaddr.sin_family = AF_INET; //设置地址类型为AF_INET,这个宏表示本地的任意IP地址,
                               //因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,
                               //这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP地址,端口号为6666。
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6666);

listen将主动套接字转为被动套接字

作用:典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的accept()返回并接受这个连接,如果有大量的客户端发起连接而服务器来不及处理,尚未accept的客户端就处于连接等待状态,listen()声明sockfd处于监听状态,并且最多允许有backlog个客户端处于连接待状态,如果接收到更多的连接请求就忽略。listen()成功返回0,失败返回-1。

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);

/*
参数:
    sockfd: 套接字,文件描述符
    backlog:排队建立3次握手队列和刚刚建立3次握手队列的链接数和 
    cat /proc/sys/net/ipv4/tcp_max_syn_backlog //查看系统默认backlog
*/
/*
返回值:
    创建成功,返回0
    失败,返回-1
*/

accept接受连接

作用:三方握手完成后,服务器调用accept()接受连接,如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来。addr是一个传出参数,accept()返回时传出客户端的地址和端口号。addrlen参数是一个传入传出参数(value-result argument),传入的是调用者提供的缓冲区addr的长度以避免缓冲区溢出问题,传出的是客户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区)。如果给addr参数传NULL,表示不关心客户端的地址。

#include <sys/types.h> 		/* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
/*
参数:
    sockfd: 套接字,文件描述符
    addr: 传出参数,返回链接客户端地址信息,含IP地址和端口号
    addrlen: 传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小
*/
/*
返回值:
    创建成功,返回新的文件描述符,用于通信
    失败,返回-1
*/

整个是一个while死循环,每次循环处理一个客户端连接。由于cliaddr_len是传入传出参数,每次调用accept()之前应该重新赋初值。accept()的参数listenfd是先前的监听文件描述符,而accept()的返回值是另外一个文件描述符connfd,之后与客户端之间就通过这个connfd通讯,最后关闭connfd断开连接,而不关闭listenfd,再次回到循环开头listenfd仍然用作accept的参数。accept()成功返回一个文件描述符,出错返回-1。

/*示例*/
while (1) {
	cliaddr_len = sizeof(cliaddr);
	connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
	n = read(connfd, buf, MAXLINE);
	......
	close(connfd);
}

connect连接建立

客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址。connect()成功返回0,出错返回-1。

#include <sys/types.h> 					/* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*
参数:
    sockfd: 套接字,文件描述符
    addr: 传入参数,指定服务器端地址信息,含IP地址和端口号
    addrlen: 传入参数,传入sizeof(addr)大小
*/
/*
返回值:
    创建成功,返回0
    失败,返回-1
*/

猜你喜欢

转载自www.cnblogs.com/Trevo/p/12615848.html