Socket:套接字linux
1、Socket是在应用层与TCP\IP协议族通讯的中间软件抽象层,它把传输层与网络层复杂的操做抽象为几个简单的接口共应用层调用已实现进程在网络中的通讯。服务器
2、套接字:源IP地址和源端口号以及目标IP地址和目的端口号的组合称为套接字。是支持TCP/IP的网络通讯的基本操做单元,能够看作是不一样主机之间的进程进行双向通讯的端点,简单的说就是通讯的两方的一种约定,用套接字中的相关函数来完成通讯过程。网络
有人将socket说成是ip+port(端口号),ip标识网络中的主机,port标识主机上的应用程序socket
2、Socket分为两种:基于文件型的(AF_UNIX)、基于网络型的(AF_INET)tcp
基于网络型(AF_INET)又分为两种:tcp、udp(不须要手动创建链接)函数
3、Socket基于网络型的TCP协议工做流程图:编码
先从服务端提及:spa
1.先初始化:socket>>>>>>>>>soc=socket.socket() 调用模块中的类产生套接字对象,操作系统
能够添加参数(三个参数:家族、类型,0),默认为基于网络型的code
2.与端口绑定:bind(元组) 参数为(ip,端口)
3.对端口进行监听:listen()
4.调用阻塞,等待客户端链接: accept() 若是客户经过connect成功链接就执行,而且 返回两个值:1.一个新的套接字
2.客户端的地址(ip和服务器相同,端口号不一样,元组的形式)
5.用新的套接字进行操做数据:1.recv(1024) 参数1024表示每次从缓冲区读取的数据 的长度
2.send(‘要发送的数据’.encode(编码方式))
客户端:
初始化客户端:socket.socket()
链接服务器:connect()
若是链接成功,此时客户端就能够发送数据,服务端就能够接受请求并处理请求,而后 把回应数据发送给客户端,客户端读取数据,最后关闭链接,一次交互结束。
4、socket模块中的socket类的初始化参数:
参数控制选择家族、模式等,默认为基于网络型的、TCP(须要创建链接)的套接字
第一个参数:选择是基于网络型,仍是基于文件型
第二个参数:选择TCP模式(须要手动创建链接),仍是UDP模式(不须要创建链接)
第三个参数:一般默认为0
5、套接字(是个对象,以下面的s)的经常使用方法:
解析关键:
1、client,addr=accept()用于接收客户端的链接请求,且会阻塞。当客户端出现connect而且地址一致时,链接成功而且执行后面的代码。
返回值1表示生成一个新的套接字:而且必须用这个新的套接字去操做数据
返回值2客户端的地址(包括客户端ip与端口号,注意同一台计算机上服务器与客户 端的ip是相同的)
2、recv是从操做系统的缓冲区中读取数据的,而且会阻塞,只有向另外一端发送数据,recv 操做系统的从缓冲区读到内容,下面的代码才会被执行。
总结:
1、默认状况下:使用的是基于网络的,且协议为TCP:
TCP是基于链接的,因此必须先启动服务端再启动客户端,不然报错。
且一次链接以后只能跟一个客户端通讯,别的服务端想实现通讯必须先让服务端与原客户端断开链接,这就用到了,循环的去接收链接。
循环接收客户端链接
循环收发数据(看上面recv介绍的循环结束条件)
当存在循环发送、接受数据时,结束条件就是客户端强行关闭,
客户端强行关闭有两种状况:
1.在linux系统中客户端强行关闭,recv会接收到空消息。不会致使服务端报错,因此判断recv的值是否为空为结束条件。
2.而window下,客户端强行关闭,recv不会接受空消息,而是直接报错。因此须要捕捉异常。而且以捕捉到异常做为结束条件。(即放在except后break)
2、基于网络的,UDP协议:(须要指明参数)
UDP套接字是无链接的,因此先启用哪一端,都不会报错。
因为UDP是无链接的,因此能够同时多个客户端与服务端同时通讯。
不须要手动创建链接:
服务端指定参数后,只须要绑定(bind)ip地址与端口号不须要监听和接收链接请求
客户端也须要指定参数,不须要connect手动链接,可直接操做数据。多个客户端可 以共存,同时向服务端发送数据。注意客户端发送数据时,要指明(ip,端口号),即 sendto(),参数出了要发送的数据,还要接上服务器的ip地址和端口号。