当前位置: 首页 > 编程日记 > 正文

python使用socket实现协议TCP长连接框架

点击上方蓝字[协议分析与还原]关注我们


 使用python实现协议中常见的TCP长连接框架。

分析多了协议就会发现,很多的应用,特别是游戏类和IM类应用,它们的协议会使用长连接的方式,来保持客户端与服务器的联系,这些长连接,通常是TCP承载的。

我们之前介绍的websocket就是长连接的一种,不过它是兼容HTTP协议的,有兴趣的朋友可以看下之前的文章:

WebSocket协议分析

如果我们要模拟这个客户端的行为,根据不同应用服务器的实现情况,有些长连接不是必须的,但有些长连接,就必须去实现它。例如最近分析的某应用,虽然它主要使用HTTP协议进行交互,但它在TCP长连接中传输了一些必须的信息,如果不实现长连接,就会有很多信息无法处理。

在python中,很容易实现HTTP协议,当然,也容易实现TCP协议,它的TCP实现,使用socket库就可以了,只是需要注意,TCP长连接中通常传输的是十六进制数据,协议非标准的,需要自行根据协议分析结果来封装数据格式。

这里以一个使用到TCP长连接的协议为样例,来给出协议的TCP长连接框架,大家有需要可以参考实现,当然,代码也是从样例中摘出来的,并不是完整的。

我的TCP长连接框架,首先是外部的包装,初始化一些参数,例如长连接使用到的ip端口及socket套接字等:

self.longip='im.langren001.com'self.longport= 6656self.threadLock = threading.Lock()self.sockmain = socket.socket(socket.AF_INET, socket.SOCK_STREAM);self.longlinktcpstart2()tlonglink = threading.Thread(target=lrsuser.longlinktcpth2,name='mainlink_'+ self.playinfo['uid'], args=(self,))tlonglink.start()self.threadinfo.append(tlonglink)

这个里面调用了两个函数,一个是longlinktcpstart2函数,作用是建立socket连接,并对一些连接建立初始时的交互进行实现,另一个是longlinktcpth2函数,是一个线程,实现对连接内的数据进行收发处理。一般来说,这两个可以在一起实现,但为了方便socket异常断开的处理,分成了两个函数。

longlinktcpstart2的实现如下:

def longlinktcpstart2(self):server_address = (self.longip, int(self.longport))self.savelogs('longlinktcpstart2', 'Connecting to %s:%d.' % server_address)self.sockmain.connect(server_address)self.databuf = b''message = genbaseinfo.genalive()self.sockmain.sendall(message)message = genbaseinfo.genfirstdata()if len(message)==0:self.savelogs('longlinktcpstart2', 'genfirstdata error ')return Falseself.sockmain.sendall(message)self.longlinkcnt=2cnt = 0while (cnt < 2):try:buf = self.sockmain.recv(2048)sz = len(buf)self.savelogs('longlinktcpstart2', "recv data len "+str(sz) )if sz > 0:self.databuf +=bufself.dealdatabuf()if cnt == 0:alivemsg =  genbaseinfo.genalive()self.sockmain.sendall(alivemsg)self.savelogs('longlinktcpstart2', "sendalive")regtime=int(round(time.time() * 1000))-random.randint(14400000,25200000)regtime=regtime*1000pcode = self.versionstr + '.0'message =  genbaseinfo.genseconddata()if len(message) == 0:self.savelogs('longlinktcpstart2', 'genseconddata error ')return Falseself.sockmain.sendall(message)self.longlinkcnt = self.longlinkcnt + 1elif cnt == 1:pcode = self.versionstr + '.0'message =  genbaseinfo.genotherdata()if len(message) == 0:self.savelogs('longlinktcpstart2', 'genthirddata error ')return Falseself.sockmain.sendall(message)self.longlinkcnt = self.longlinkcnt + 1cnt = cnt + 1else:self.savelogs('longlinktcpstart2', 'recv data alive')except:  # socket.errorself.savelogs('longlinktcpstart2', 'socket error,do connect fail')return Falsereturn True

这里面的genbaseinfo 相关的函数可以忽略,是用来生成发送的消息数据的实现,用自己的函数去替换即可。dealdatabuf函数是用来处理收到的消息数据实现,这两个都要根据具体的协议分析情况去实现,注意,生成的用来发送的数据和接收到的需要处理的数据,都需要按十六进制处理,这里不做详述。

线程longlinktcpth2是一个循环,协议不退出,循环不结束,实现如下:

def longlinktcpth2(self):tmalive = 0;r_inputs = set()r_inputs.add(self.sockmain)w_inputs = set()w_inputs.add(self.sockmain)e_inputs = set()e_inputs.add(self.sockmain)tm=int(round(time.time()))self.savelogs('longlinktcpth2', 'enter' )while (self.quitflag==0):try:r_list, w_list, e_list = select.select(r_inputs, w_inputs, e_inputs, 1)for event in r_list:try:buf = event.recv(2048)sz = len(buf)self.savelogs('longlinktcpth2', "loop recv data len:"+ str(sz) )if sz > 0:self.databuf += bufself.dealdatabuf()alivemsg = genbaseinfo.genalive()self.sockmain.sendall(alivemsg)self.savelogs('longlinktcpth2', "sendalive")else:self.savelogs('longlinktcpth2', "远程断开连接,do reconnect")r_inputs.clear()time.sleep(3)self.sockmain = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.longlinktcpstart2()r_inputs = set()r_inputs.add(self.sockmain)w_inputs = set()w_inputs.add(self.sockmain)e_inputs = set()e_inputs.add(self.sockmain)except Exception as e:self.savelogs('longlinktcpth2', str(e))self.threadLock.acquire()if (len(self.msglist) > 0):msg = self.msglist.pop(0)self.threadLock.release()self.sockmain.sendall(msg)self.savelogs('longlinktcpth2',"send a msg")else:self.threadLock.release()tmnow=int(round(time.time()))if tmnow-tm>30:message = genbaseinfo.genotherdata()if len(message) == 0:self.savelogs('longlinktcpth2', 'genalivedata error ')return Falseself.sockmain.sendall(message)self.savelogs('longlinktcpth2', "send alivemsg"+str(self.longlinkcnt))self.longlinkcnt = self.longlinkcnt + 1 #这个要一条连接统一,不能乱,回头加锁tm=tmnowif len(w_list) > 0:  # 产生了可写的事件,即连接完成self.savelogs('longlinktcpth2',str(w_list))w_inputs.clear()  # 当连接完成之后,清除掉完成连接的socketif len(e_list) > 0:  # 产生了错误的事件,即连接错误self.savelogs('longlinktcpth2', str(e_list))e_inputs.clear()  # 当连接有错误发生时,清除掉发生错误的socketexcept OSError as e:self.savelogs('longlinktcpth2', 'socket error,do reconnect')time.sleep(3)self.sockmain = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.longlinktcpstart2()r_inputs = set()r_inputs.add(self.sockmain)w_inputs = set()w_inputs.add(self.sockmain)e_inputs = set()e_inputs.add(self.sockmain)self.savelogs('longlinktcpth2', 'leave')

由于这个代码主要是在windows上使用,因此,longlinktcpth2线程采用了select来实现,而没有使用epoll。在循环中,对异常进行了处理,如果发生异常,连接被断开,则调用longlinktcpstart2重新连接,而不退出循环,其余的和longlinktcpstart2里面一致。

由于TCP连接是流的概念,因此,需要对数据进行缓存拼接,这就是上面代码中databuf的作用,防止每次收到的数据不完整或者太多,方便后续的处理,这才是一个合格的码农的信仰的自我升华。

至此,python下协议TCP长连接的实现就结束了,大家如果有类似的需要,可以参考实现。

欢迎大家常来坐坐,多来交流。

别忘点“在看”、“赞”和“分享”

新的规则,及时收推文要先给公号星标

别忘了星标一下,不然就错过了

7fd5dd22f78595e5a773820aaeb979dd.png

长按进行关注,时刻进行交流。

相关文章:

哈夫曼编码与解码

这是我的第一篇博客&#xff0c;希望大神们批评指正。 首先介绍以下什么是哈夫曼树&#xff08;来自百度百科&#xff09; 哈夫曼树─即最优二叉树&#xff0c;带权路径长度最小的二叉树&#xff0c;经常应用于数据压缩。 在计算机信息处理中&#xff0c;“哈夫曼编码”是一种一…

012-python基础-数据运算

1、算数运算&#xff1a; 2、比较运算 3、赋值运算 4、逻辑运算 5、成员运算&#xff1a; 6、身份运算&#xff1a; 7、位运算&#xff1a; 8、运算符优先级&#xff1a; 转载于:https://www.cnblogs.com/chhphjcpy/p/6064572.html

优化XCode的编译速度

1.将Debug Information Format改为DWARF 在工程对应Target的Build Settings中&#xff0c;找到Debug Information Format这一项&#xff0c;将Debug时的DWARF with dSYM file改为DWARF。 这一项设置的是是否将调试信息加入到可执行文件中&#xff0c;改为DWARF后&#xff0c;如…

给windows装个Mac黑苹果虚拟机

点击上方↑↑↑蓝字[协议分析与还原]关注我们“ windows下安装使用苹果Mac虚拟机。”平常的生活工作中&#xff0c;我大部分时候使用Windows&#xff0c;偶尔用用Mac。实在是用不惯Mac&#xff0c;但有的时候&#xff0c;有些工作还是需要在Mac上搞&#xff0c;不得不用&#x…

Ajax基础讲解 1

随着web的不断发展&#xff0c;Ajax的运用越来越普及&#xff0c;但是对很多同学来说Ajax稍微有些难懂&#xff0c;今天呢就简单给大家讲解一下Ajax的一些基础入门的知识&#xff0c;希望可以帮到刚学习Ajax的同学。 第一步&#xff1a;首先就是服务器的搭建&#xff0c;关于服…

在虚拟机linux环境下编译windows版adb fastboot

原文出自&#xff1a;http://blog.chinaunix.net/uid-20546441-id-1746200.html我根据虚拟机编译遇到的问题进行一些添加【前提条件】Linux Android源码完整虚拟机磁盘空间100G左右&#xff08;60G用来存放代码和编译后的文件&#xff09;swap 30G左右&#xff0c;若太小会导致…

PC端微信小程序wxapkg解密

sh点击上方↑↑↑蓝字[协议分析与还原]关注我们“ 解密PC端wxapkg文件。”用过微信pc版的应该都知道&#xff0c;PC上也可以使用微信小程序。这个小程序用起来和手机端差不多&#xff0c;不过&#xff0c;在分析时&#xff0c;确是有差别的——PC上的wxapkg文件是加密的。无论如…

cron 定时器简单入门

cron:计划任务&#xff0c;是任务在约定的时间执行已经计划好的工作&#xff0c;根据配置文件约定的时间来执行特定的任务。 编写测试类继承 IJob &#xff0c;实现Execute 此方法就是用于定时的任务 配置定时时间&#xff1a; 先创建windows服务&#xff0c;服务创建详情 Inst…

PHP5.5.13 + Apache2.4.7安装配置流程详解

---恢复内容开始--- 自学PHP的这段时间里&#xff0c;真是倍感辛酸&#xff0c;相信广大的菜鸟们应该很我感同身受吧&#xff0c;在查阅了网上和众多数资料后&#xff0c;总结出来想当比较全面的安装方法&#xff0c;拿出来与广大的编程爱好者一起分享哈。 首先到官网上下载相关…

cocos2dx小游戏数据签名算法破解

点击上方↑↑↑蓝字[协议分析与还原]关注我们“ 快速破解小游戏常见的数据签名算法。”最近在分析各种小游戏的协议&#xff0c;本文以《我不是无双》这款小游戏为样例介绍这类小游戏的分析方法。01—抓包在分析开始&#xff0c;首先明确分析的目的是学习这款游戏的网络协议算法…

laravel5 MAC is invalid

如果本机的环境更换过,项目中用来加密Crypt组件中的参数会变更. 如果出现这个问题,得更换数据库中加密后的变量 stackoverflow上找到的解决方法都是 composer dump-autoload composer clear-cache 之后再清空浏览器缓存 其实最简单的解决方法是将数据库中的所有数据重新encrpt一…

不大于N的所有素数

算法如下&#xff1a; #include<stdio.h> #include<math.h> void Sieve(int n) {int p,j,i;int A[n1],L[n1];for(p2;p<n;p)A[p]p;for(p2;p<sqrt(n);p){if(A[p]!0){jp*p;while(j<n){A[j]0;jjp;}}}i0;for(p2;p<n;p){if(A[p]!0){L[i]A[p];i;}}for(p0;p<…

3集合与函数类型

import UIKit var str “Hello, playground” // 1 数组 // 创建一个空的数组 var arr1 Int; arr1.append(6); // 创建一个特定大小 并且所有数据都被默认的构造方法 // 以下数组有6个5 var arr2 Array(repeating: 5, count: 6); // 通过两个数组相加创建一个数组 var a…

非凡推崇_2015年值得推崇的25位编码者

非凡推崇by freeCodeCamp通过freeCodeCamp 2015年值得推崇的25位编码者 (25 Coders Worth Following on Twitter in 2015) Our community upvoted the following 25 coders, in no particular order, as “Coders Worth Following in 2015”:我们的社区对以下25位编码员进行了…

CSS中各种各样居中方法的总结

在开发前端页面的时候&#xff0c;元素的居中是一个永远都绕不开的问题。看似简单的居中二字&#xff0c;其实蕴含着许许多多的情况&#xff0c;对应着很多的处理方法&#xff0c;本文就试图对页面布局中的居中问题进行总结~~ 居中问题分为水平居中和竖直居中两种&#xff1b;而…

iOS 流式播放音频文件

方式一&#xff1a; https://github.com/tumtumtum/StreamingKit 方式二&#xff1a; https://github.com/AlexanderYeah/SK_PlayOnWavFileDemo

java 创建 HMAC 签名

ava 创建 HMAC 签名 psd素材 1. []ComputopTest.java package com.javaonly.hmac.test; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import …

2014年数字:我的人生在命令行中

by freeCodeCamp通过freeCodeCamp 2014年数字&#xff1a;我的人生在命令行中 (2014 in Numbers: My Life Behind the Command Line) For 2014, I decided to simplify my life. Rather than pursuing a variety of human experiences, as I had previously, I wanted to focu…

c# unity PlayerPrefs 游戏存档,直白点就是讲游戏数据本地保存下来

在游戏会话中储存和访问游戏存档。这个是持久化数据储存&#xff0c;比如保存游戏记录。 我的理解是通过某个特殊的标签来保存在本地&#xff0c;而且该标签为key的意思&#xff0c;初始值不用赋值。 在游戏开发中较为实用。 暂时用到了 SetInt(string key, int value); 还有Ge…

4-类和结构体和可选类型

import UIKit var str “Hello, playground” // 1 枚举语法 // 与 C 和 Objective-C 不同&#xff0c;Swift 的枚举成员在被创建时不会被赋予一个默认的整型值 // 书写方式一 enum sizeType{ case small case middle case large } // 书写方式二 enum sizeNumber { case x,…

android处理url中的特殊字符

java处理url中的特殊字符&#xff08;如&,%...&#xff09; URL(Uniform Resoure Locator&#xff0c;统一资源定位器)是Internet中对资源进行统一定位和管理的标志。 一个完整的URL包括如下内容&#xff1a; 应用协议名称&#xff0c;包括http,ftp,file等标志 资源定位…

图的连通性和连通分量_英语,人口,连通性和露营地

图的连通性和连通分量by Evaristo Caraballo通过Evaristo Caraballo 英语&#xff0c;人口&#xff0c;连通性和露营地 (English, Population, Connectivity and Campsites) 在世界范围内推动使用Free Code Camp的因素 (Factors driving the use of Free Code Camp worldwide)…

jQuery源码分析系列:属性操作

属性操作 1.6.1相对1.5.x最大的改进&#xff0c;莫过于对属性.attr()的重写了。在1.6.1中&#xff0c;将.attr()一分为二&#xff1a; .attr()、.prop()&#xff0c;这是一个令人困惑的变更&#xff0c;也是一个破坏性的升级&#xff0c;会直接影响到无数的网站和项目升级到1.6…

HDU 5972 Regular Number(ShiftAnd+读入优化)

【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid5972 【题目大意】 给出一个字符串&#xff0c;找出其中所有的符合特定模式的子串位置&#xff0c;符合特定模式是指&#xff0c;该子串的长度为n&#xff0c;并且第i个字符需要在给定的字符集合Si中 【题解】 利用Sh…

把握机缘_机缘巧合,蒙太奇训练以及我的朋友如何使自己失业

把握机缘by Wiley Jones通过威利琼斯 机缘巧合&#xff0c;蒙太奇训练以及我的朋友如何使自己失业 (Serendipity, training montages, and how my friend automated himself out of a job) “No one person’s Hollywood success story has anything in common with anybody e…

Servlet(一)

BS架构的优势 1.数据库之负责数据库的管理 2.Web服务器负责业务逻辑的处理 3.浏览器提供操作界面 4.不需要单独安装客户端 5.开发相对于CS简单&#xff0c;客户端和服务器的通信模块都是使用标准的HTTP协议进行通信 CS架构 1.数据库作为Server,使用数据库特定的编程语言编写业务…

visual webgui theme designer

转载于:https://www.cnblogs.com/jintan/p/3804095.html

51单片机编码自学_这是9个月的自学式编码看起来像什么

51单片机编码自学by Stephen Mayeux斯蒂芬马约(Stephen Mayeux) 这是9个月的自学式编码看起来像什么 (Here’s What 9 Months of Self-Taught Coding Looks Like) 只是划伤表面 (Just Scratching the Surface) Today marks 9 months since I embarked on my journey as a self…

19.Remove Nth Node From End of List

方法1&#xff1a;由于链表不能随机访问&#xff0c;所以很自然的想法是第一遍得到链表长度&#xff0c;然后计算倒数第n个结点的位置&#xff0c;但这样时间复杂度O(n2)&#xff0c;想到用空间换取时间&#xff0c;可以用一个地址数组存储每个结点的地址&#xff0c;然后直接删…

HTML 5中SEO可以用那些代码来做优化

头部代码 1、标题标签(title标签) 在HTML5中标题标签依然存在&#xff0c;其仍然具有不可替代的作用;不过我们看到还有更多的可供搜索引擎识别的代码&#xff0c;我们将改代码的等级微降。 2、元标签(meta标签) 字符集编码声明标签 该标签原本就是搜索引擎必看且首先要看的标签…