TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
URG: 标识紧急指针是否有效
ACK: 标识确认序号是否有效
PSH: 用来提示接收端应用程序立刻将数据从tcp缓冲区读走
RST: 要求重新建立连接. 我们把含有RST标识的报文称为复位报文段
SYN: 请求建立连接. 我们把含有SYN标识的报文称为同步报文段
FIN: 通知对端, 本端即将关闭. 我们把含有FIN标识的报文称为结束报文段
第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
第一次分手:主机1(可以使客户端,也可以是服务器端),设置Sequence Number和Acknowledgment Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;
第二次分手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我也没有数据要发送了,可以进行关闭连接了;
第三次分手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入CLOSE_WAIT状态;
第四次分手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。
使用TCP的协议:
http 80 ftp 20 21 telnet 23 ssh 22 smtp 25
使用UDP协议:
tftp 69 dhcp 67 68 snmp 161 162
dns tcp udp 53
1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
4.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5、TCP对系统资源要求较多,UDP对系统资源要求较少。
实现网络进程之间的通信,几乎所有的应用程序都是采用socket,“一切皆socket”。
Http协议:对应于应用层。Http协议是基于TCP链接的。
tcp协议:对应于传输层
ip协议: 对应与网络层
TCP/IP是传输层协议,主要解决数据如何在网络中传输;而Http是应用层协议,主要解决如何包装数据。
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
Http连接:http连接就是所谓的短连接,及客户端向服务器发送一次请求,服务器端相应后连接即会断掉。
socket连接:socket连接及时所谓的长连接,理论上客户端和服务端一旦建立连接,则不会主动断掉;但是由于各种环境因素可能会是连接断开,比如说:服务器端或客户端主机down了,网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该链接已释放网络资源。所以当一个socket连接中没有数据的传输,那么为了位置连续的连接需要发送心跳消息,具体心跳消息格式是开发者自己定义的。
Socket的英文原义是“孔”或“插座”,通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
(1)服务器监听:ip+端口号
(2)客户端请求:发出向 服务器 的 ip以及端口连接请求
(3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
linux系统
编译PHP时必须在配置中添加--enable-sockets 配置项来启用。
可以使用 lnmp一键安装包:https://github.com/lampol
windows (不推荐使用,这里不介绍)
server.php
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($socket,'0.0.0.0',6666);
socket_listen($socket);
$sock = socket_accept($socket);
$res = socket_read($sock,2048);
echo $res;
socket_write($sock,'hello client');
client.php
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_connect($socket,'127.0.0.1',6666);
$msg = 'hlllo server';
socket_write($socket,$msg);
$res = socket_read($socket,2048);
echo $res;
首先运行: php server.php
官方文档:http://php.net/manual/zh/book.sockets.php
//创建一个套接字(通讯节点)
resource socket_create ( int $domain , int $type , int $protocol )
//获取错误码
$errcode = socket_last_error();
//获取错误信息 根据错误码
$errmsg = socket_strerror($errcode);
//绑定套接字资源 地址 以及端口
bool socket_bind ( resource $socket , string $address [, int $port = 0 ] )
socket
用 socket_create() 创建的一个有效的套接字资源。
address
如果套接字是 AF_INET 族,那么 address 必须是一个四点分法的 IP 地址(例如 127.0.0.1 )。
如果套接字是 AF_UNIX 族,那么 address 是 Unix 套接字一部分(例如 /tmp/my.sock )
port (可选)
参数 port 仅仅用于 AF_INET 套接字连接的时候,并且指定连接中需要监听的端口号。
//监听被绑定的socket 地址端口
bool socket_listen ( resource $socket [, int $backlog = 0 ] )
//接受客户端的连接 阻塞的
resource socket_accept ( resource $socket )
//连接指定的套接字资源
bool socket_connect ( resource $socket , string $address [, int $port = 0 ] )
//传数据到套接字
int socket_write ( resource $socket , string $buffer [, int $length = 0 ] )
int socket_send ( resource $socket , string $buf , int $len , int $flags )
//读取 socket 传过来的数据
string socket_read ( resource $socket , int $length [, int $type = PHP_BINARY_READ ] )
//注意:server端的 应该是 accept 返回的资源
int socket_recv ( resource $socket , string &$buf , int $len , int $flags )
//关闭套接字 资源
void socket_close ( resource $socket )
//获取连接过来的客户端ip地址和端口 socket 连接过来的套接字资源
socket_getpeername ( resource $socket , string &$address [, int &$port ] )
//设置套接字选项
socket_set_option ( resource $socket , int $level , int $optname , mixed $optval )
$socket socket_create或者socket_accept的函数返回值
$level 这个值 SOL_SOCKET
$optname
SO_REUSEADDR 是让套接字端口释放后立即就可以被再次使用
SO_RCVTIMEO 是套接字的接收资源的最大超时时间
SO_SNDTIMEO 是套接字的发送资源的最大超时时间
$optval
参数3假如是后两个,则参数4是一个这样的数组array('sec'=>1,'usec'=>500000),如果是第一个 就是true 或者false
//获取套接字选项
socket_get_option ( resource $socket , int $level , int $optname )
//实现io多路复用 返回活跃的连接
socket_select ( array &$read , array &$write , array &$except , int $tv_sec [, int $tv_usec = 0 ] )
注意 :前三个参数都是引用传值。
$read 服务端监听的套接字资源,当它有变化(就是有新消息到或者有客户端连接/断开)时,socket_select函数才会返回,继续往下执行。
$write是监听是否有客户端写数据,传入NULL是不关心是否有写变化。
$except是$sockets里面要被排除的元素,传入NULL是”监听”全部。
第四个参数为null为阻塞, 为0位非阻塞, 为 >0 为等待时间
返回 活跃的链接数 当有连接 或数据操作时就会返回