套接口地址结构:在中定义
struct sockaddr_in
{ uint8_t sin_len // 该数据类型在type.h中定义,表示该结构的长度
sa_family sin_family // 表明是tcp还是udp
in_port_t sin_port //相应的端口
struct in_addr sin_addr //ip地址 struct in_addr{in_addr_t s_addr;}
}
但是上面的结构基本不用,而是使用在中定义的通用套接口地址结构
struct sockaddr{
uint8_t sa_len //8进制的无符号数
sa_family_t sa_family;
char sa_data[14]
}
下面就是套接口编程的主要函数:套接口函数了,都定义在中,客户端与服务器端要使用的函数是不一样的。
服务器程序先开:
(1)int socket(int family, int type, int protocol)
family表示使用的协议,用宏表示, AF_INET 表示ip4, AF_INET6 表ip6
type表示套接口类型,用宏表示,SOCK_STREAM表示字节流套接字 SOCK_DGRAM 表示数据包套接
字 SOCK_RAW表示原始套接字
protocol 表示协议,用宏表示 IPPROTO_TCP表示tcp协议 IPPROYO_UDP表示udp协议
函数成功返回一个非负整数,叫做套接字描述符,类似与文件描述符,服务器用这个描述符作为监听描述符,往后与客户端连接时还会生成连接描述符。
(2)int bind(int sockfd, const struct sock_addr *myaddr, socketlen_t addrlen)
将上一步的套接口描述符与一个套接字地址结构绑定。
(3)int listen(int sockfd, int backlog);
将上一步的套接口(处于closed状态)转化成listen状态,允许内核接受向该套接口的连接请求。
(4) int accept( int sockfd, struct sockaddr *cliaddr ,socket_len *addlen)
当client有对sockfd的连接请求时,建立连接,得到cli的套接字地址结构 cliaddr,产生连接套接字,以后与客户端发送信息就使用这个套接字。cliet没有连接请求时阻塞自己。由于一个服务器对应多个客户端,所以该函数一般位于死循环中,每次建立连接就fork一个子进程去处理与客户端的通信。
客户端再开
(1)socket 得到连接套接字,客户端只有一个套接字
(2)int connect(int sockfd, const struct sockaddr * servaddr, socklen_t addrle)
利用连接套接字发起tcp连接,该函数将激发tcp的3次握手过程。servaddr必须事先定义,因此服务器
的ip与服务器bind的自己端的端口号(大部分是周知端口)必须实现约定好,客户端这边的端口号可以由内核随机开一个端口
客户端与服务器之间的tcp连接就建立起来了,双方就可以通信了,结束后使用close()将套接字的引用计数减1.
流程就是这样,虽然看着简单,但是是基于内核将所有复杂的事情都做完了。
阅读(631) | 评论(0) | 转发(0) |