首页 > 代码库 > socket编程
socket编程
一、CS架构
server端要求:
1、力求一直提供服务
2、绑定到一个唯一的地址,让客户端找到
二、socket
socket就是为了完成C/S架构软件的开发,但是如果是C/S架构的软件就一定需要解决双方通信问题。
若基于网络通信就需要了解复杂的网络协议 TCP/IP协议,于是socket出现了;
1、什么是sock?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的
2、socket分类
(1)基于文件类型的套接字家族
套接字家族的名字:AF_UNIX
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信(Linux操作系统)
(2)基于网络类型的套接字家族 AF_INET
(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)(ssh,nginx,mysql)
3、soket套接字的工作流程
服务端:得到Socket对象,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。
客户端:客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。
C/S交换阶段:客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束
服务端套接字函数
s.bind() 绑定(主机,端口号)到套接字
s.listen() 开始TCP监听
s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来
客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
4、基于TCP协议的套接字
(1)实现一个简单的套接字
import socket phon=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建一个基于网络的(socket.AF_INET)tcp协议传输的sock(socket.SOCK_STREAM) phon.bind(("127.0.0.1",8090)) #把创建好的套接字,绑定在 唯一的IP和端口上。 phon.listen(80) #开始监听 conn,addr=phon.accept() #等待客户端通过TCP三次握手发起 连接 (把某个连接,和连接的对象分解赋值给 conn,和addr) data=http://www.mamicode.com/conn.recv(1024) #接收 连接进来的某一个客户端,发送过来的消息 print("接受到来自客户端发来的消息",data) conn.send(data.upper()) #发送接受的消息 给某一个客户端
执行结果
服务端:
客户端:
(2)循环通信的套接字
虽然上述已经实现了一个简单的套接字,但服务端的 socket 只能接受一次客户端的连接,所以可以利用while..Ture构建一个通信循环
服务端:
import socket phon=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建一个基于网络的(socket.AF_INET)tcp协议传输的sock(socket.SOCK_STREAM) phon.bind(("127.0.0.1",8090)) #把创建好的套接字,绑定在 唯一的IP和端口上。 phon.listen(80) #开始监听 conn,addr=phon.accept() #等待客户端通过TCP三次握手发起 连接 (把某个连接,和连接的对象分解赋值给 conn,和addr) while True: #循环通信-----------------------------------------------------------------------> data=http://www.mamicode.com/conn.recv(1024) #接收 连接进来的某一个客户端,发送过来的消息 print("接受到来自客户端发来的消息",data) conn.send(data.upper()) #发送接受的消息 给某一个客户端 conn.close() phon.close()
客户端:
import socket phon=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phon.connect((‘127.0.0.1‘,8090)) #客户端的phon.connect正好对于服务端的phon1.accept() while True: #循环通信----------------------------------------------------------------------------------->> mes=input(‘---->: ‘.strip()) if not mes: continue res=phon.send(mes.encode(‘utf-8‘)) #发消息 data=http://www.mamicode.com/phon.recv(1024) #收消息 print(data.decode(‘gbk‘)) phon.close()
tcp服务端
import socket import subprocess iphon=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #(建立一个socket对象) iphon.bind((‘127.0.0.1‘,8080)) #绑定到 IP+端口上 成为唯一的socket iphon.listen(5) #设置连接池的个数 print(‘starting........‘) while True: #连接循环 conn,addr=iphon.accept() #等待电话连接 print(‘电话线路是‘,conn) print(‘客户手机号:‘,addr) while True: #通信循环 发送和接收 try: data=conn.recv(1024) #接受消息 最大从内存里接受1024MB数据 print(‘客户端发来的消息是%s‘%data) data=data.decode(‘utf-8‘) #从客户端发来的数据是经过编码的字节数据 所以需要解码 成Unicode res=subprocess.Popen( data, shell=True, stdout=subprocess.PIPE) #解码后传进subprocess.Popen去cmd执行 data1 = res.stdout.read().decode(‘gbk‘) #cmd是gbk编码所以需要gbk解码 print(data1) #打印解码后的结果 data1=data1.encode(‘gbk‘) #编码 conn.send(data1) #发送消息 #编码后再传输给客户端 except Exception: break conn.close() iphon.close() #
TCP客户端
import socket phon=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phon.connect((‘127.0.0.1‘,8080)) #客户端的phon.connect正好对于服务端的phon1.accept() while True: #循环通信 mes=input(‘---->: ‘.strip()) if not mes: continue res=phon.send(mes.encode(‘utf-8‘)) #发消息 data=http://www.mamicode.com/phon.recv(1024) #收消息 print(data.decode(‘gbk‘)) phon.close()
socket编程