[Python 网络编程] TCP Client (四)
TCP Client
- 客户端编程步骤:
- 创建socket对象
- 连接到服务端的ip和port,connect()方法
- 传输数据
- 使用send、recv方法发送、接收数据
- 关闭连接,释放资源
最简单的客户端:
#TCP Client客户端
import socket client = socket.socket()
client.connect(('127.0.0.1',9999)) client.send("Hi, I'm client1.".encode())
client.close() #运行
服务端状态:
[16:08:25] [showthreads,1796] [<_MainThread(MainThread, started 9816)>, <Thread(show_client, started daemon 9344)>, <Thread(accept, started daemon 5908)>, <Thread(showthreads, started 1796)>]
[16:08:26] [accept,5908] <socket.socket fd=424, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 5287)>-('127.0.0.1', 5287)
[16:08:26] [show_client,9344] {('127.0.0.1', 5287): <_io.TextIOWrapper mode='rw' encoding='utf8'>}
2017/12/24 16:08:26 127.0.0.1:5287
Hi, I'm client1. [16:08:26] [recv,980] 2017/12/24 16:08:26 127.0.0.1:5287
Hi, I'm client1. [16:08:26] [recv,980] ('127.0.0.1', 5287) quit
[16:08:28] [showthreads,1796] [<_MainThread(MainThread, started 9816)>, <Thread(show_client, started daemon 9344)>, <Thread(accept, started daemon 5908)>, <Thread(showthreads, started 1796)>]
将上面的TCP Client封装成类:
1)搭架子
#TCP Client客户端 封装成类
import socket class ChatClient:
def __init__(self):
pass def start(self):
pass def _recv(self):
pass def send(self):
pass def stop(self):
pass
2)基础功能
客户端:
#TCP Client客户端 封装成类
import socket,threading,logging,datetime
DATEFMT="%H:%M:%S"
FORMAT = "[%(asctime)s]\t [%(threadName)s,%(thread)d] %(message)s"
logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt=DATEFMT) class ChatClient:
def __init__(self,ip='127.0.0.1',port=9999):
self.sock = socket.socket()
self.addr = (ip,port) self.event = threading.Event()
self.start() def start(self):
self.sock.connect(self.addr) # 准备接收数据,recv是阻塞的,启动新的线程
threading.Thread(target=self._recv,name='recv').start() def _recv(self):
while not self.event.is_set():
try:
data = self.sock.recv(1024) #阻塞 except Exception as e:
logging.info(e) #有任何异常保证退出
break
msg = "{:%H:%M:%S} {}:{}\n{}\n".format(datetime.datetime.now(),*self.addr,data.decode().strip())
# print(type(msg),msg)
logging.info("{}".format(data.decode())) def send(self,msg:str):
data = "{}\n".format(msg.strip()).encode()
self.sock.send(data) def stop(self):
logging.info("{} broken".format(self.addr))
self.sock.close() self.event.wait(3)
self.event.set()
logging.info("byebye") def main():
e = threading.Event()
cc = ChatClient() while True:
msg = input(">>> ")
if msg.strip() == 'quit':
cc.stop()
break
cc.send(msg) if __name__ == '__main__':
main()
服务端:
#TCP Server 改装成makefile
import threading,logging,time,random,datetime,socket
DATEFMT="%H:%M:%S"
FORMAT = "[%(asctime)s]\t [%(threadName)s,%(thread)d] %(message)s"
logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt=DATEFMT) class ChatServer:
def __init__(self,ip='127.0.0.1',port=9999): #启动服务
self.addr = (ip,port)
self.sock = socket.socket()
self.event = threading.Event() self.clients = {} #客户端 def show_client(self):
while not self.event.is_set():
if len(self.clients) > 0:
logging.info(self.clients)
self.event.wait(3) def start(self):
self.sock.bind(self.addr)
self.sock.listen()
# accept会阻塞主线程,所以开一个新线程
threading.Thread(target=self._accept,name='accept',daemon=True).start()
threading.Thread(target=self.show_client,name='show_client',daemon=True).start() def stop(self):
for c in self.clients.values():
c.close()
self.sock.close()
self.event.wait(3)
self.event.set() def _accept(self):
while not self.event.is_set(): #多人连接
conn,client = self.sock.accept() #阻塞
f = conn.makefile(mode='rw')
self.clients[client] = f logging.info("{}-{}".format(conn,client))
# recv 默认阻塞,每一个连接单独起一个recv线程准备接收数据
threading.Thread(target=self._recv, args=(f, client), name='recv',daemon=True).start() def _recv(self, f, client): #接收客户端数据
while not self.event.is_set():
try:
data = f.readline()
except Exception:
data = 'quit'
finally:
msg = data.strip()
# Client通知退出机制
if msg == 'quit':
f.close()
self.clients.pop(client) logging.info('{} quit'.format(client))
break msg = "{:%Y/%m/%d %H:%M:%S} {}:{}\n{}\n".format(datetime.datetime.now(),*client,data)
# msg = data
print(msg)
logging.info(msg) for c in self.clients.values():
# print(type(msg))
c.writelines(msg)
c.flush() cs = ChatServer()
print('!!!!!!!!!!!')
cs.start()
print('~~~~~~~~~~~~~~~~~~~~')
e = threading.Event()
def showthreads(e:threading.Event):
while not e.wait(3):
logging.info(threading.enumerate()) threading.Thread(target=showthreads,name='showthreads',args=(e,)).start() while not e.wait(1): # Sever控制台退出方式
cmd = input('>>> ').strip()
if cmd == 'quit':
cs.stop()
e.wait(3)
break
运行结果:
#服务端
~~~~~~~~~~~~~~~~~~~~
>>> [17:26:14] [show_client,7824] {('127.0.0.1', 7517): <_io.TextIOWrapper mode='rw' encoding='cp936'>}
[17:26:14] [accept,3832] <socket.socket fd=400, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 7517)>-('127.0.0.1', 7517)
[17:26:15] [showthreads,5928] [<Thread(accept, started daemon 3832)>, <Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(showthreads, started 5928)>]
[17:26:17] [show_client,7824] {('127.0.0.1', 7517): <_io.TextIOWrapper mode='rw' encoding='cp936'>}
[17:26:18] [showthreads,5928] [<Thread(accept, started daemon 3832)>, <Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(showthreads, started 5928)>]
[17:26:19] [recv,2112] 2017/12/24 17:26:19 127.0.0.1:7517
hello1 2017/12/24 17:26:19 127.0.0.1:7517
hello1 [17:26:20] [show_client,7824] {('127.0.0.1', 7517): <_io.TextIOWrapper mode='rw' encoding='cp936'>}
[17:26:21] [showthreads,5928] [<Thread(accept, started daemon 3832)>, <Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(showthreads, started 5928)>]
[17:26:23] [show_client,7824] {('127.0.0.1', 7517): <_io.TextIOWrapper mode='rw' encoding='cp936'>}
[17:26:23] [accept,3832] <socket.socket fd=436, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 7539)>-('127.0.0.1', 7539)
[17:26:24] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>]
2017/12/24 17:26:25 127.0.0.1:7539
[17:26:25] [recv,6748] 2017/12/24 17:26:25 127.0.0.1:7539
hello2
hello2 [17:26:26] [show_client,7824] {('127.0.0.1', 7517): <_io.TextIOWrapper mode='rw' encoding='cp936'>, ('127.0.0.1', 7539): <_io.TextIOWrapper mode='rw' encoding='cp936'>}
[17:26:27] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>]
[17:26:29] [show_client,7824] {('127.0.0.1', 7517): <_io.TextIOWrapper mode='rw' encoding='cp936'>, ('127.0.0.1', 7539): <_io.TextIOWrapper mode='rw' encoding='cp936'>}
[17:26:30] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>]
[17:26:32] [show_client,7824] {('127.0.0.1', 7517): <_io.TextIOWrapper mode='rw' encoding='cp936'>, ('127.0.0.1', 7539): <_io.TextIOWrapper mode='rw' encoding='cp936'>}
[17:26:33] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>]
[17:26:35] [show_client,7824] {('127.0.0.1', 7517): <_io.TextIOWrapper mode='rw' encoding='cp936'>, ('127.0.0.1', 7539): <_io.TextIOWrapper mode='rw' encoding='cp936'>}
[17:26:36] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>]
#客户端1
>>> hello1
[17:26:19] [recv,2604] 2017/12/24 17:26:19 127.0.0.1:7517
hello1
>>> [17:26:25] [recv,2604] 2017/12/24 17:26:25 127.0.0.1:7539
hello2 [17:26:37] [recv,2604] [WinError 10054] 远程主机强迫关闭了一个现有的连接。
#客户端2
>>> hello2
>>> [17:26:25] [recv,4044] 2017/12/24 17:26:25 127.0.0.1:7539
hello2 [17:26:37] [recv,4044] [WinError 10054] 远程主机强迫关闭了一个现有的连接。
以上例子在客户端,如果服务端主动断开,客户端需要异常处理。
[Python 网络编程] TCP Client (四)的更多相关文章
- python 网络编程 TCP/IP socket UDP
TCP/IP简介 虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多. 计算机为了联网,就必须规定通信协议,早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Micro ...
- python网络编程-TCP协议中的三次握手和四次挥手(图解)
建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资 ...
- python网络编程 - tcp
网络编程 低级别的网络服务 高级别的网络服务 socket又称“套接字”,应用程序通过“套接字”向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯. tcp 传输控制协议(Tra ...
- python 网络编程 -- Tcp协议
Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可. 客户端 大多数连接都是可靠 ...
- python网络编程--TCP连接的三次握手(三报文握手)与四次挥手
一.TCP连接 运输连接有三个阶段: 连接建立.数据传送和连接释放. 在TCP连接建立过程中要解决以下三个问题: 1,要使每一方能够确知对方的存在. 2.要允许双方协商一些参数(如最大窗口之,是否使用 ...
- [Python 网络编程] TCP编程/群聊服务端 (二)
群聊服务端 需求分析: 1. 群聊服务端需支持启动和停止(清理资源); 2. 可以接收客户端的连接; 接收客户端发来的数据 3. 可以将每条信息分发到所有客户端 1) 先搭架子: #TCP Serve ...
- [Python 网络编程] TCP、简单socket模拟ssh (一)
OSI七层模型(Open System Interconnection,开放式系统互联) 应用层 网络进程访问应用层: 为应用程序进程(例如:电子邮件.文件传输和终端仿真)提供网络服务: 提供用户身份 ...
- python 网络编程 tcp和udp 协议
1. 网络通信协议 osi七层,tcp\ip五层 tcp\ip五层 arp协议:通过IP地址找到mac地址 2.tcp和udp的区别 tcp协议:面向连接,消息可靠,相对udp来讲,传输速度慢,消息是 ...
- python网络编程--TCP客户端的开发
#导入socket模块 2 import socket 3 #参数说明 4 """ 5 socket类的介绍 6 创建客户端socket对象 7 socket.socke ...
随机推荐
- 6 springboot Docker 部署
安装请参考其他的教程请参考http://www.runoob.com/docker/centos-docker-install.htm 拉取zookeeper镜像 docker pull zookee ...
- python学习之老男孩python全栈第九期_day021知识点总结——包、异常处理
一. 包 # 把解决一类问题的模块放在同一个文件夹里 -- 包 # 创建目录代码# import os# os.makedirs('glance/api')# os.makedirs('glance/ ...
- C#语言数据类型
整数类型 sbyte -128~127之间 byte 0~255 short(Int16) -32768~32768 ushort(UInt16) 0~65535 Int (Int32) ...
- tensorboard实现tensorflow可视化
1.工程目录 2.data.input_data.py的导入 在tensorflow更新之后可以进行直接的input_data的导入 # from tensorflow.examples.tutori ...
- 【PyQt5 学习记录】002:添加部件及网格布局
#!/usr/bin/python3 # -*- coding:utf-8 -*- import sys from PySide2.QtWidgets import (QApplication, QW ...
- JS 数据容量转换/换算
function diskSize(num){ if (num == 0) return '0 B'; var k = 1024; //设定基础容量大小 var sizeStr = ['B','KB' ...
- System Monitor ArcGIS系统监控利器
System Monitor是Esri推出的GIS系统监控工具,对于GIS数据中心的运维人员是难得的利器.早期版本是开源免费的解决方案,在今年的Esri 全球用户大会上,Esri宣布将发行商业版的Sy ...
- CentOS6.5(4)----宿主机无法访问虚拟机中的web服务解决方案
宿主机无法访问虚拟机中的web服务 在Windows7宿主机中的VMware虚拟机中安装了CentOS6.5操作系统,并且基于Nginx搭建了Web服务器,网页刚刚搭建好的时候,通过宿主机的浏览器可以 ...
- volley3--Volley类
Volley这个类,Volley作为整个框架的入口,其实就是创建了一个RequestQueue队列 public class Volley { /** * Default on-disk cache ...
- 安卓性能优化之清除Handler的Message和Runnable
安卓性能优化之清除Handler的Message和Runnable Handler是由系统所提供的一种异步消息处理的常用方式,一般情况下不会发生内存泄露. 但既然是调优,当在A_Activity中使用 ...