1.1socket编程之tcp编程

"""
socket类型
sock_stream 面向连接的流套接字,默认值 tcp协议
sock_dgram 无连接的数据报文套接字,udp协议
"""
import socket
s = socket.socket()
s.bind(('127.0.0.1',9999)) #bind接受一个2元祖
s.listen()
"""
Accept a connection. The socket must be bound to an address and listening for connections.
The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection,
and address is the address bound to the socket on the other end of the connection
"""
new_socker,info = s.accept() #只接受一个client请求,阻塞
data=new_socker.recv(1024)  #阻塞
print(data)
print(type(data))
new_socker.send('back {}'.format(data).encode())
s.close()  

 例子

有阻塞就要尽量放到线程中去执行,不要影响主线程
import socket
server = socket.socket()
server.bind(('127.0.0.1',9999))
server.listen()
'''
建立一个client,socket连接之后,只能发一次数据
在accept出阻塞,需要建立第二个连接
'''
while True:
new_socket,ip = server.accept()
data = new_socket.recv(1024)
new_socket.send('ck test {}'.format(data).encode())

socket群聊实例

import socket
import threading class ChatTcpServer:
def __init__(self,ip,port):
self.ip = ip
self.port = port
self.cliets = {}
#实例化就创建一个socket对象
self.socket = socket.socket()
def start(self):
self.socket.bind((self.ip,self.port))
self.socket.listen()
threading.Thread(target=self._accept,name="_aceept").start() def _accept(self): #只开启一个accept线程,连接产生的new_socket负责和线程receive同信
while True:
print('1~~~~~~~~~~~~~~~~~~~',threading.enumerate())
new_socket,raddr = self.socket.accept() #阻塞主线程,所以开启一个工作线程receive
threading.Thread(target=self._receive,name="reveive",args=(new_socket,)).start()
self.cliets[new_socket] = raddr
print(self.cliets)
print(type(self.cliets.keys())) def _receive(self,new_socket): #客户端连接几个socket 就开几个receive线程
while True:
print('2~~~~~~~~~~~~~~~~~~~',threading.enumerate())
data = new_socket.recv(1024) #阻塞
for k in self.cliets.keys():
k.send('ack {}'.format(data).encode()) def stop(self):
for s in self.cliets.values():
s.close()
self.socket.close() if __name__ == '__main__':
cs = ChatTcpServer('127.0.0.1',9999)
cs.start()
# print('3~~~~~~~~~~~~~~~~~~~',threading.enumerate())
# cs.stop()
problem:there has a error when cliens exit
ConnectionAbortedError
import socket
import threading class ChatTcpServer:
def __init__(self,ip,port):
self.ip = ip
self.port = port
self.cliets = {}
#实例化就创建一个socket对象
self.socket = socket.socket()
self.event = threading.Event()
def start(self):
self.socket.bind((self.ip,self.port))
self.socket.listen()
threading.Thread(target=self._accept,name="_aceept").start() def _accept(self): #只开启一个accept线程,连接产生的new_socket负责和线程receive同信
while not self.event.is_set():
new_socket,raddr = self.socket.accept() #阻塞主线程,所以开启一个工作线程receive
threading.Thread(target=self._receive,name="reveive",args=(new_socket,)).start()
self.cliets[new_socket] = raddr
print(self.cliets)
print(type(self.cliets.keys())) def _receive(self,new_socket): #客户端连接几个socket 就开几个receive线程
while not self.event.is_set():
data = new_socket.recv(1024) #阻塞
for k in self.cliets.keys():
k.send('ack {}'.format(data).encode()) def stop(self):
if self.cliets:
for s in self.cliets.values():
s.close()
self.socket.close()
self.event.set() if __name__ == '__main__':
cs = ChatTcpServer('127.0.0.1',9999)
cs.start()
while True:
cmd = input("please set stop:>>>")
if cmd == 'quit':
cs.stop()
break
以上版本服务端可以断开连接,但是客户端断开连接抛出异常 

增加客户端断开命令

客户端主动断开连接的问题,服务端知道自己何时断开
如果是客户端断开服务器不知道,所有好的做法客户端发出特殊消息通知服务器断开连接,但是客户端主动断开服务端主动发送一个空消息,超时返回异常,捕获异常并清理连接,即使为客户端提供了断开命令,也不能保证客户端会使用它断开连接,还是要增加这个退出功能
    def _receive(self,new_socket): #客户端连接几个socket 就开几个receive线程
while not self.event.is_set():
data = new_socket.recv(1024) #阻塞
if data == b"quit":
self.cliets.pop(new_socket)
new_socket.close()
break
for k in self.cliets.keys():
k.send('ack {}'.format(data).encode())

 socket常用方法

socket = socket.socket()
socket.recv(1024) bufsize=1024 获取数据,默认是阻塞状态
socket.recvfrom(1024) 获取数据,返回一个二元组(bytes,address)
socket.recv_into(buffer=1024,nbytes=10,flags=None) 获取到nbytes的数据后,存储到buffer中,如果nbytes没有指定或者0,将buffer大小的数据存入buffer中,返回接收的字节数
socket.send(bytes) tcp发送设备
socket.sendall(bytes) tcp发送全部设备,成功返回None

Makefile

socket.socket().makefile(mode='r',buffering=None)   创建一个与该套接字相关联的文件对象,将recv方法看作读方法,将send方法看作写方法
socket.getpeername()    返回连接套接字的远程地址,返回值通常是元组(ipaddr,port)
sockete.getsockname() 返回套接字自己的地址,通常是一个元祖(ipaddr,port)
socket.setbloking(flag) 如果flag为0则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)
非阻塞模式下,如果调用recv没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常
socket.settimeout(value) 设置套接字操作的超时期,timeout是一个浮点数单位秒
值为none表示没有超时期,一般超时期应该在刚创建套接字时设置,因为他们可能用于连接的操作(connect())

 read和readline(行读取,包括换行符)

import socket
socket = socket.socket()
socket.bind(('127.0.0.1',9999))
socket.listen() while True:
new_socket,raddr = socket.accept()
f = new_socket.makefile('rw')
print(f)
line = f.readline() #Read and return one line from the stream
line = f.read(10) #Read up to n bytes from the object and return them
#只有输入十个字节才会return
print(line)
f.write('ack {}'.format(line))
f.flush()
f.close()

client编写

import socket
socket = socket.socket()
socket.bind(('127.0.0.1',9999)) #server ip
socket.listen() new_socket,raddr = socket.accept()
data = new_socket.recv(1024)
print(data)
new_socket.send('ack {}'.format(data).encode())
import socket
import threading
import datetime
import logging FORMAT = '%(asctime)s %(threadName)s %(thread)d %(message)s'
logging.basicConfig(level=logging.INFO,format=FORMAT) class ChatClient:
def __init__(self,ip='127.0.0.1',port=9999):
self.ip = ip
self.port = port
self.sock =socket.socket()
self.event = threading.Event() def start(self):
self.sock.connect((self.ip,self.port))
self.send('i am ready')
threading.Thread(target=self.receive,name='receive').start() def receive(self):
while not self.event.is_set():
try: #连接不成功,捕获异常
data = self.sock.recv(1024)
logging.info(data)
except Exception as e:
logging.info(e) def send(self,msg:str):
self.sock.send('{}'.format(msg).encode()) def stop(self):
self.sock.close()
self.event.set()
logging.info('Client stops') def main():
cc = ChatClient()
cc.start()
while True:
cmd = input("please set a number:")
if cmd.strip() == b'quit':
cc.stop()
break
cc.send(cmd) if __name__ == '__main__':
main()

Python之socket_tcp的更多相关文章

  1. python socket 函数介绍

    socket 函数原型:socket.socket([family[,type[,proto]]]) family参数取值(协议族): socket.AF_INET        -->ipv4 ...

  2. Python中的多进程与多线程(一)

    一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...

  3. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  4. Python 小而美的函数

    python提供了一些有趣且实用的函数,如any all zip,这些函数能够大幅简化我们得代码,可以更优雅的处理可迭代的对象,同时使用的时候也得注意一些情况   any any(iterable) ...

  5. JavaScript之父Brendan Eich,Clojure 创建者Rich Hickey,Python创建者Van Rossum等编程大牛对程序员的职业建议

    软件开发是现时很火的职业.据美国劳动局发布的一项统计数据显示,从2014年至2024年,美国就业市场对开发人员的需求量将增长17%,而这个增长率比起所有职业的平均需求量高出了7%.很多人年轻人会选择编 ...

  6. 可爱的豆子——使用Beans思想让Python代码更易维护

    title: 可爱的豆子--使用Beans思想让Python代码更易维护 toc: false comments: true date: 2016-06-19 21:43:33 tags: [Pyth ...

  7. 使用Python保存屏幕截图(不使用PIL)

    起因 在极客学院讲授<使用Python编写远程控制程序>的课程中,涉及到查看被控制电脑屏幕截图的功能. 如果使用PIL,这个需求只需要三行代码: from PIL import Image ...

  8. Python编码记录

    字节流和字符串 当使用Python定义一个字符串时,实际会存储一个字节串: "abc"--[97][98][99] python2.x默认会把所有的字符串当做ASCII码来对待,但 ...

  9. Apache执行Python脚本

    由于经常需要到服务器上执行些命令,有些命令懒得敲,就准备写点脚本直接浏览器调用就好了,比如这样: 因为线上有现成的Apache,就直接放它里面了,当然访问安全要设置,我似乎别的随笔里写了安全问题,这里 ...

随机推荐

  1. rpc error: code = Internal desc = stream terminated by RST_STREAM with error code: PROTOCOL_ERROR

    使用grpc-go调用grpc服务端时,出现rpc error: code = Internal desc = stream terminated by RST_STREAM with error c ...

  2. 嵌入式开发之网络心跳包---阻塞和非阻塞以及是否有必要心跳包heartbeat

    1.1 TCP和UDP的心跳包是用来维持长连接的 心跳包只是用来检测socket的链接状态 2.1 非阻塞情况下TCP 心跳包是否有必要建立心跳包 需要, a.如果说 严格 检测掉线的话 那么不管是不 ...

  3. (原)关于MEPG-2中的TS流数据格式学习

    关于MEPG-2中的TS流数据格式学习 Author:lihaiping1603 原创:http://www.cnblogs.com/lihaiping/p/8572997.html 本文主要记录了, ...

  4. Vue之初识Vue

    前言 如果你之前已经习惯了用jQuery操作DOM,学习Vue.js时请先抛开手动操作DOM的思维, 因为Vue.js是数据驱动的,你无需手动操作DOM.它通过一些特殊的HTML语法,将DOM和 数据 ...

  5. 聊聊IOCP,聊聊异步编程

    *:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !impor ...

  6. 【深入Java虚拟机】一 JVM类加载过程

    首先Throws(抛出)几个自己学习过程中一直疑惑的问题: 1.什么是类加载?什么时候进行类加载? 2.什么是类初始化?什么时候进行类初始化? 3.什么时候会为变量分配内存? 4.什么时候会为变量赋默 ...

  7. 编译PHP扩展amqp & php消息队列 rabbitmq

    首先介绍下AMQP: AMQP——高级消息队列协议,目前比较有名气的实现大概就是大名鼎鼎的RabbitMQ了. RabbitMQ是一个在AMQP基础上完成的,可复用的企业消息系统.他遵循Mozilla ...

  8. [转] C#中的delegate 和 event

    转至:here 终于会用c#中的delegate(委托) 作者:qq826364410 引言 Delegate是Dotnet1.0的时候已经存在的特性了,但由于在实际工作中一直没有机会使用Delega ...

  9. AWS事故总结,几招教你规避风险

    版权声明:本文由王煜奕原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/90687001488360802 来源:腾云阁 ht ...

  10. 转载>>C# Invoke和BeginInvoke区别和使用场景

    转载>>C# Invoke和BeginInvoke区别和使用场景 一.为什么Control类提供了Invoke和BeginInvoke机制? 关于这个问题的最主要的原因已经是dotnet程 ...