Python中实现socket通信,socket通信的服务端比较复杂,而客户端非常简单,所以客户端基本上都是用sockct模块实现,而服务

端用有很多模块可以使用。下面就说一下服务端可使用的模块。

模块名 简介 使用情况
socket 最原始,最低端的模块,如果你想亲自体验socket的整个实现过程,那就用它吧 不用
SocketServer 它把socket的实现进行了很好的封装,比如server端要为每个TCP连接创建一个新的线程/进程等等,这些你不用关心,它会帮你搞定,用户的主要工作是写已连接TCP/UDP的处理方法handle() 比较常用
select 在一个线程/进程中同时监控处理多个已连接好的socket 比较常用
Twisted 很牛逼的一个模块,功能很强大,已经算是一个框架了 比较常用
其它异步框架

如gevent等

比较常用

下面用上面几个常用的模块实现TCP类型socket通信:Client端发送字符串,Server端收到后在数据前加处理线程/进程的id返回,Client端收到后打

印出来。Client端如果输入的是空字符,那就关闭Client的socket,接着结束该Client进程(它会触发Server端对应的connected_socket.recv()返回空

字符串,关闭connect_sock。以下都是在Windows上运行通过。如果想结束server或client端,那就直接kill就行了,它会自动释放占用的所有资源。

1、使用socket模块

Server(多线程实现)

在Winows下,子进程的入口参数不是能有socket类对象,详见http://bugs.python.org/issue11119,所以要想实现多进程比较麻烦;而Linux上没

有这个问题,在下面代码的基础上很小的修改就行实现。Server端监听TCP连接,对于建立好的每个连接,监听进程为其创建一个线程/进程,并检测线程/

进程的状态,如果已结束,那就进行收尾工作。监听进程使用的是非阻塞Socket(不是立即返回,有超时),这是因为监听进程除了处理新连接之外还要检

查子进程的状态。如果设定成阻塞,那它将所有已建立的连接POP出来由交由子线程后,就会一直阻塞在accept(),如果一直没有新的已建立好的连接,那它

就会一直阻塞下去,就没有办法检测子线程的状态了。所以为了既能检查已建立的连接队列又能检查子进程的状态,需把该socket设置成非阻塞。handle()是

为每个建立好的连接创建的子线程的入口。

#-*- coding:utf-8 -*-

import socket
import threading BUFSIZE = 1024
def handle(connected_sock):
while True:
data = connected_sock.recv(BUFSIZE)
if len(data) >0:
print 'receive:',data
cur_thread = threading.current_thread()
send_data = '{}:{}'.format(cur_thread.ident,data)
connected_sock.sendall(send_data) #用sendall,不要用send,send并不一定发送所有send_data,可能发送了部分就返回了
print 'send:',send_data
else:
print 'close the connected socket and terminate sub thread'
connected_sock.close()
break HOST = ''
PORT = 12356
ADDR = (HOST,PORT)
sub_threads = [] listen_sock = socket.socket()
listen_sock.settimeout(5.0) #设定超时时间后,socket其实内部变成了非阻塞,但有一个超时时间
listen_sock.bind(ADDR)
listen_sock.listen(2)
print 'build connect when new TCP comes' while True:
try:
connected_sock,client_addr = listen_sock.accept()
except socket.timeout:
length = len(sub_threads)
while length:
sub = sub_threads.pop(0)
sub_id = sub.ident #进程ID
sub.join(0.1) #等待线程结束,0.1秒
if sub.isAlive():
sub_threads.append(sub)
else:
print 'killed sub thread ',sub_id
length -=1
else:
t = threading.Thread(target=handle,name='sub thread',args=(connected_sock,))
#它继承了listen_socket的阻塞/非阻塞特性,因为listen_socket是非阻塞的,所以它也是非阻塞的
#要让他变为阻塞,所以要调用setblocking
connected_sock.setblocking(1)
t.start()
sub_threads.append(t)

Client端

#-*- coding:utf-8 -*-

import socket
HOST = 'localhost'
PORT = 12356
ADDR =(HOST,PORT)
BUFSIZE = 1024 sock = socket.socket()
try:
a = sock.connect(ADDR)
except Exception,e:
print 'error',e
sock.close()
sys.exit() print 'have connected with server' while True:
data = raw_input('> ')
if len(data)>0:
print 'send:',data
sock.sendall(data) #不要用send()
recv_data = sock.recv(BUFSIZE)
print 'receive::',recv_data
else:
sock.close()
break

 2、SocketServer模块

Server(多线程实现,Linux下建议用多进程)

      在Linux上可以用多进程实现,基本上把下面代码中的ThreadingTCPServer改为ForkingTCPServer就可以了。在Windows下无法用多进程,因为

SocketServer为每个已连接创建进程时,用的是os.fork(),windows上没有fork() API,哎,干嘛不搞个兼容Windows的API啊。

可以看到,下面的代码非常简洁,用户不用去子线程的结束后,父进程对它的收尾,也不用关心socket的关闭。这些都由SocketServer完成。

Handler中的handle()方法与上面用socket模块写的handle方法基本相同。

#-*- coding:utf-8 -*-
from SocketServer import BaseRequestHandler,ThreadingTCPServer
import threading BUF_SIZE=1024 class Handler(BaseRequestHandler):
def handle(self):
while True:
data = self.request.recv(BUF_SIZE)
if len(data)>0:
print 'receive=',data
cur_thread = threading.current_thread()
response = '{}:{}'.format(cur_thread.ident,data)
self.request.sendall(response)
print 'send:',response
else:
print 'close'
break if __name__ == '__main__':
HOST = ''
PORT = 12356
ADDR = (HOST,PORT)
server = ThreadingTCPServers(ADDR,Handler) #参数为监听地址和已建立连接的处理类
print 'listening'
server.serve_forever() #监听,建立好TCP连接后,为该连接创建新的socket和线程,并由处理类中的handle方法处理

Socket通信的Python实现的更多相关文章

  1. Python Socket通信原理

    [Python之旅]第五篇(一):Python Socket通信原理   python Socket 通信理论 socket例子 摘要:  只要和网络服务涉及的,就离不开Socket以及Socket编 ...

  2. Python简易聊天工具-基于异步Socket通信

    继续学习Python中,最近看书<Python基础教程>中的虚拟茶话会项目,觉得很有意思,自己敲了一遍,受益匪浅,同时记录一下. 主要用到异步socket服务客户端和服务器模块asynco ...

  3. Python进阶----UDP协议使用socket通信,socketserver模块实现并发

    Python进阶----UDP协议使用socket通信,socketserver模块实现并发 一丶基于UDP协议的socket 实现UDP协议传输数据 代码如下:

  4. python - socket通信笔记

    参考: 通过编写聊天程序来熟悉python中多线程和socket的用法:https://www.cnblogs.com/mingjiatang/p/4905395.html python socket ...

  5. 【Socket通信】关于Socket通信原理解析及python实现

    Socket(套接字)通信{网络通信其实就是Socket间的通信},首先了解下概念:[来源于百度百科] "两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.& ...

  6. python udp socket通信

    前段时间学习了一下c++的socket通信,但发现那玩意儿比较复杂还是转向python了,下面就是一个简单的udpsocket通信程序,欢迎大佬前来指正 udp聊天 import socket # 创 ...

  7. 【转】Python学习---Socket通信原理以及三次握手和四次挥手详解

    [原文]https://www.toutiao.com/i6566024355082404365/ 什么是Socket? Socket的中文翻译过来就是"套接字".套接字是什么,我 ...

  8. Python socket 通信功能简介

    常用的地址家族AF_UNIX:基于文件,实现同一主机不同进程之间的通信AF_INET:基于网络,适用于IPv4AF_INET6:基于网络,使用于IPv6 常见的连接类型SOCK_STREAM:即TCP ...

  9. Day 6-2简单的socket通信

    什么是socket? Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面 ...

随机推荐

  1. ip防刷脚本

    #!/bin/sh #防刷脚本 #env ACCESS_PATH=/home/wwwlogs ACCESS_LOG=y.log IPTABLES_TOP_LOG=iptables_top.log DR ...

  2. /etc/profile /etc/profile .bash_profile .bashrc解释

    1.用户登录系统时,bash首先执行/etc/profile配置文件和/etc/profile.d/目录下的配置文件,这些配置文件对系统的所有用户都有效,它们设置了普遍性的环境变量. 2.然后,Bas ...

  3. ECMAScript 面向对象JS学习笔记1

    1.对象的 prototype 属性,可以把它看成创建新对象所依赖的原型.===在我理解,就是prototype下设置的字段是唯一性的,共享性的,不管创建多少个对象,所处空间都是不变的,没有增加也没有 ...

  4. JWNL的配置使用

    JWNL是什么? JWNL is an API for accessing WordNet-style relational dictionaries. It also provides functi ...

  5. 基于WordNet的英文同义词、近义词相似度评估及代码实现

    源码地址:https://github.com/XBWer/WordSimilarity 1.确定要解决的问题及意义 在基于代码片段的分类过程中,由于程序员对数据变量名的选取可能具有一定的规范性,在某 ...

  6. jQuery属性操作(三)

    在阅读attr.remove方法时,看到一些对浏览器兼容性做处理的hooks.接下来看一下这些hooks都做了哪些兼容性处理 1.attrHooks.主要处理IE6-9 input的type属性无法写 ...

  7. Linux 下安装JDK1.8

    本文主要介绍的是如何是Linux环境下安装JDK的,因为Linux环境下,很多时候也离不开Java的,下面笔者就和大家一起分享如何jdk1.8的过程吧. 一.安装环境 操作系统:Red Hat Ent ...

  8. How to Use Postman to Manage and Execute Your APIs

    How to Use Postman to Manage and Execute Your APIs Postman is convenient for executing APIs because ...

  9. 路由器子网掩码设置不正确导致github无法访问

    奇怪的现象,路由器子网掩码设置成255.0.0.0会导致电脑访问不到https://github.com/ 改成默认的255.255.255.0就正常了.

  10. Laravel 5.1 中如何使用模型观察者

    有时候我们需要在一个表更改后,触发某个事件,最常见的比如,首页推荐商品 1 更改了,需要清空所有首页商品缓存. 首先我们需要在建立一个观察者类,比如 App\Model\Observers\Proje ...