python_day9_socket,,1、socket套接


1、socket套接字工作流程图

2、收发功能

3、不间断一发一收

4、多客户端连接

5、UDP:收发功能

6、UDP:实现时间功能

7、执行命令


socket套接字工作流程图

技术分享图片

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束


AF_UNIX: 基于文件编程

基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信


AF_INET: 基于网络编程有AF_INET6 ipv6

CS架构


SOCK_STREAM: TCP协议 数据流式通信

SOCK_DGRAM: UDP协议 数据报式的套接字



## 收发功能

socket服务端importsocketcat=socket.socket(socket.AF_INET,socket.SOCK_STREAM)cat.bind(('192.168.0.12',9090))cat.listen(4)conn,addr=cat.accept()msg=conn.recv(1024)conn.close()print('接收到的信息:%s'%msg)conn.send(msg.upper())cat.close()socket客户端importsocketcat=socket.socket(socket.AF_INET,socket.SOCK_STREAM)cat.connect(('192.168.0.12',9090))cat.send('xiong'.encode('utf-8'))data=cat.recv(1024)print('接收到的信息:%s'%data)


#服务端会主动断开 已经传输完客户端数据的连接,将状态改变为TIME_WAIT, 四次挥手之后确定数据已经完全传输完,直接断开并清理状态连接信息


# 收发都是在操作自己的缓存区

# recv 接收的字节, 由recv用户态的应用程序发起

# 回车: 当前 socket 内核态缓存没数据 对端内核态也就没法收到数据,自然也就卡死了


##不间断一发一收

socket服务端importsocketcat=socket.socket(socket.AF_INET,socket.SOCK_STREAM)cat.bind(('127.0.0.1',9009))cat.listen(5)conn,addr=cat.accept()whileTrue:msg=conn.recv(1024)#回车:当前socket内核态缓存没数据对端内核态也就没法收到数据,自然也就卡死了print('接收到的信息:%s'%msg.decode('utf-8'))ifmsg==b'q':breakinp=input('输入一个值:')conn.send(inp.encode('utf-8'))continueconn.close()cat.close()socket客户端importsocketcat=socket.socket(socket.AF_INET,socket.SOCK_STREAM)cat.connect(('127.0.0.1',9009))whileTrue:inp=input('输入一个值:')ifinp=='q':cat.send(inp.encode('utf-8'))breakcat.send(inp.encode('utf-8'))msg=cat.recv(1024)print('接收到的信息:%s'%msg.decode('utf-8'))continuecat.close()


## 多客户端连接

# 1、当客户端与服务端建立连接,每次最大客户端连接数由listen控制,我这里最大是5个连接

# 2、多个客户端与服务端建立连接,每次只能有一个客户端与服务端通信,其它队列都会保持在队列中

# 3、unix有些系统使用try except无法解决客户端conn连接突然中断, 可以使用 if not conn: break

socket服务端importsocketcat=socket.socket(socket.AF_INET,socket.SOCK_STREAM)cat.bind(('192.168.2.192',9009))cat.listen(5)whileTrue:#客户端退出,如果队列中还有连接那么再重新建立连接conn,addr=cat.accept()#连接一次whileTrue:#与单个用户建立连接try:msg=conn.recv(1024)#当客户端关掉连接,而服务端连接却没有中断,它就直接报错ConnectionResetError:[WinError10054]exceptException:breakprint('接收到的信息:%s'%msg.decode('utf-8'))ifmsg==b'q':breakconn.send(msg.upper())conn.close()#关闭连接cat.close()#关闭程序socket客户端importsocketcat=socket.socket(socket.AF_INET,socket.SOCK_STREAM)cat.connect(('192.168.2.192',9009))whileTrue:inp=input('输入一个值:')ifinp=='q':cat.send(inp.encode('utf-8'))breakcat.send(inp.encode('utf-8'))msg=cat.recv(1024)print('接收到的信息:%s'%msg.decode('utf-8'))continuecat.close()


UDP:收发功能

1、udp不需要建立accept连接,因为无需三次握手建立一条固定的通道

2、多个客户端同时连接服务端,可同时收发信息

3、udp可以接受空 (直接回车)???


recv在自己这端的缓冲区为空时,阻塞

recvfrom在自己这端的缓冲区为空时,就收一个空

UDP_socket服务端importsocketip_port=('127.0.0.1',9999)udp_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)udp_sock.bind(ip_port)whileTrue:data,addr=udp_sock.recvfrom(1024)print(data)udp_sock.sendto(data,addr)UDP_socket客户端importsocketip_port=('127.0.0.1',9999)udp_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)whileTrue:inp=input('>>:')udp_sock.sendto(inp.encode('utf-8'),ip_port)data,addr=udp_sock.recvfrom(1024)print(data)


UDP:实现时间功能

# 1、实现时间功能

# 2、data传递进来是二进制的格式,在strftime之前需要先将格式转换回来

# 3、注意格式转换,发送都是encode,接受基本都是recvfrom

#udp_socket_server端importsocketimporttimeip_port=('127.0.0.1',9001)udp_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)udp_sock.bind(ip_port)whileTrue:data,addr=udp_sock.recvfrom(1024)print(data)ifnotdata:default_time='%Y-%m-%d%X'else:default_time=data.decode('utf-8')udp_back_time=time.strftime(default_time)udp_sock.sendto(udp_back_time.encode('utf-8'),addr)#udp_socket_client端importsocketudp_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)ip_port=('127.0.0.1',9001)#TypeError:sendto()takes2or3arguments(1given)需要带地址whileTrue:inp=input('>>:')udp_client.sendto(inp.encode('utf-8'),ip_port)data,addr=udp_client.recvfrom(1024)print('现在时间是:%s'%data.decode('utf-8'))
#1、先运行服务端#2、再运行客户端打印结果如下:现在时间是:18>>:%Y现在时间是:2018>>:现在时间是:2018-01-0420:49:53>>:


### 执行命令

#socketTCP服务端importsocketimportsubprocessip_port=('127.0.0.1',9001)ip_connect=5buff_size=1024command=socket.socket(socket.AF_INET,socket.SOCK_STREAM)command.bind(ip_port)command.listen(ip_connect)whileTrue:#客户端断开之后保持重连data,addr=command.accept()print('客户端连接信息:%s'%data)whileTrue:try:#接收客户端传递过来的值cmd_value=data.recv(buff_size)exceptException:break#执行传递过来的命令,将结果保存到管道对象中赋值给resres=subprocess.Popen(cmd_value.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.PIPE)#取出stderr的值,如果是空那么执行stdout,不为空说明报错了err=res.stderr.read()iferr:cmd_res=errelse:cmd_res=res.stdout.read()ifnotcmd_res:#判断如果是类似cd..的命令,它到subprocess值为空cmd_res='命令为空'.encode('gbk')data.send(cmd_res)continuedata.close()command.close()#socket_客户端importsocketip_port=('127.0.0.1',9001)ip_connect=5buff_size=1024command=socket.socket(socket.AF_INET,socket.SOCK_STREAM)command.connect(ip_port)whileTrue:cmd_inp=input('请输入命令:').strip()ifnotcmd_inp:commandifcmd_inp=='quit':breakcommand.send(cmd_inp.encode('utf-8'))data=command.recv(buff_size)print(data.decode('gbk'))command.close()#最后在客户端这边输入dir就能看到结果了#最后在客户端这边输入dir就能看到结果了


python_day9_socket

评论关闭