目录
总述:我们知道因特网客户端和服务器通过在连接上发送和接受字节流来通信,HTTP协议在应用层,应用层在传输层(TCP/UDP)经过协议栈封装。TCP又如何通过三握四挥建立和关闭连接呢?客户端和服务端的通信起始于socket编程,socket和TCP和HTTP关系是什么?HTTP又如何通过服务器给客户端提供动态和静态内容?参数和返回结果如何传递?看完本文,你就会有明确的解答。
套接字
1、套接字接口
总述:客户端首先需要与服务端建立连接,一个连接用四元组表示(客户端Ip:客户端端口号,服务端ip:服务端端口号)。socket是存放在内核空间的一段内存,对于linux来说,套接字就是一个文件,通过创建文件描述符,往fd里read write来向互联网通信。那么:
该文件是怎样存放的呢?
套接字存放在sockaddr_in的结构中
ip socket address structure
sockaddr_in
struct in_addr{ //定义该结构来表示IPv4地址
in_addr_t s_addr; //32位IPv4的地址
};
struct sockaddr_in{ //套接字地址结构
uint8_t sin_len; //1字节,表示整个结构的长度=16字节
sa_family_t sin_family; //1字节AF_INET,表示是IPv4地址族
in_port_t sin_port; //2字节,uint16_t,16位的端口号,0~65535
struct in_addr sin_addr; //4字节,32位IPv4地址,大端存放
char sin_zero[8]; //8字节,unused,用来补充位数,一般为0
};
general socket address structure(for connect bind accept)
struct sockaddr{
uint16_t sa_famaily; /*protocal famaily*/
char sa_data[14]; /address data*/
}
如何创建套接字文件描述符呢?
int socket(int domain, int type, int protocal)
eg
socket(AF_INET, SOCK_STREAM, 0)
客户端和服务端使用socket返回的套接字描述符仅仅返回一个部分打开的描述符,还不能读写。
如何打开套接字描述符呢
下一步描述客户端和服务端分别怎样打开套接字描述符
客户端通过connect建立和服务端的连接
int connect(int clientfd, /*客户端的socket文件描述符*/
const struct sockaddr *addr, /*服务端的套接字地址*/
socket_t addrlen/*sizeof(sockaddr_in))
客户端通过connect函数试图与套接字地址为addr的服务端建立socket连接。
如果成功,得到由套接字对(客户端IP:客户端端口,服务端IP:服务端端口)刻画的连接
客户端套接字中的端口号是由内核自动分配的,称为临时端口
服务端套接字中的端口号一般是和服务对应的知名端口,egweb服务使用端口80,电子邮件使用25.
服务端通过bind、listen、accept和客户端建立连接
int bind(int sockfd, /*服务端的socket文件描述符*/
const struct sockaddr* addr, /*服务端套接字地址*/
socklen_t addrlen /*sizeof(sockaddr_in));