专栏首页授客的专栏Python 标准类库 - 因特网协议与支持之socketserver

Python 标准类库 - 因特网协议与支持之socketserver

socketserver 模块,简化网络服务编写任务。

创建服务的步骤

1 通过子类化BaseRequestHandler 类,创建一个请求处理程序,并且重写handle()方法,该方法将处理接收到的请求

2 传递服务器地址和请求处理程序类参数,实例化server类(如TCPServer)

3 调用server对象的handle_request()、serve_forever()方法,处理单个、多个请求

实例

socketserver.TCPServer

服务端(单线程服务器)

#!/usr/bin/env python 3.4.0
#-*- encoding:utf-8 -*-
__author__ = 'shouke'
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
    """
    供server使用的RequestHandler类.
    每个客户端连接连接到服务器时都会被初始化一次,并且必须重写handle()方法以便同客户端交流。
    """
    def handle(self):
        while True:
            # self.request即为与客户端连接的TCP socker
            self.data = self.request.recv(1024).decode('utf-8').strip()
            print('receive data from client[host:%s port:%s]:%s' % (self.client_address[0], self.client_address[1], self.data))
            if self.data == 'bye':
                self.request.sendall(bytes('bye', encoding='utf-8'))
                self.request.close()
                break
            else:
                self.request.sendall(self.data.upper().encode('utf-8'))
if __name__ == '__main__':
    # 创建TCPSocket服务器,绑定到10.118.52.26地址上,端口8000
    server = socketserver.TCPServer(('10.118.52.26', 8000), MyTCPHandler)
    # 激活服务器,让服务器一直运行,直到按Ctrl+C
    server.serve_forever()
客户端

#!/usr/bin/env python 3.4.0

#-*- encoding:utf-8 -*-

__author__ = 'shouke'

import socket

import time

if __name__ == '__main__':

if_sock_connected = False

try:

# Create a socket (SOCK_STREAM means a TCP socket)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect to server and send data

sock.connect(('10.118.52.26', 8000))

if_sock_connected = True # 标记socket是否已连接

i = 0

while i < 100:

if i == 6:

sock.sendall(bytes('bye\n', "utf-8"))

else:

sock.sendall(bytes('hello world with tcp\n', "utf-8"))

# Receive data from the server

received = str(sock.recv(1024), "utf-8")

logger.info('receive data from server:%s' % received)

if received == 'bye':

break

time.sleep(5)

i += 1

except Exception as e:

logger.error('程序运行出错:%s' % e)

finally:

if if_sock_connected:

sock.close()

运行结果

函数说明:

BaseServer.serve_forever(poll_interval=0.5)

处理shudown请求除外的请求。

有关socket说明

socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

使用给定的地址家族,socket 类型,协议号创建一个新的socket。

family:默认为AF_INET,其它可选值有AF_INET6, AF_UNIX, AF_CAN or AF_RDS

type:默认为SOCK_STREAM,其它可选值有 SOCK_DGRAM, SOCK_RAW ,或者其它SOCK_XXX常量

protocol:通常为0或者忽略,当family为AF_CAN时,为CAN_RAW、CAN_BCM

Socket 对象

socket.close()

标记socket为closed

close()释放与连接关联的资源,但不一定立即关闭连接。如果要及时关闭连接,请在调用close()之前调用shutdown()。

socket.connect(address)

连接给定地址的远程socket

socket.recv(bufsize[, flags])

从socket接收数据。返回值即为接收的数据。

buffsize:每次接收的最大数据量。.

flags默认为0

注意:为了同硬件和网络设备最佳匹配,buffsize应该为一个相对小的2次幂,比如4096

socket.sendall(bytes[, flags])

发送字节数据到socket。不同于send方法,该方法会持续发送bytes参数给定的数据,直到所有数据被发送、错误发生。如果发送成功,则返回None,否则抛出异常。没有方法判断到底成功发送了多少数据

socket.send(bytes[, flags])

发送字节数据到socket。返回发送字节数,如果只传输了部分数据,程序会尝试发送剩余数据。

更多资料参考官方文档,socket模块

服务端(多线程服务器)

#!/usr/bin/env python 3.4.0

#-*- encoding:utf-8 -*-

__author__ = 'shouke'

import socket

import threading

import socketserver

class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):

def handle(self):

while True:

# self.request即为与客户端连接的TCP socker

self.data = self.request.recv(1024).decode('utf-8').strip()

cur_thread = threading.current_thread()

print('%s receive data from client[host:%s port:%s]:%s' % (cur_thread.name, self.client_address[0], self.client_address[1], self.data))

if self.data == 'bye':

self.request.sendall(bytes('bye', encoding='utf-8'))

self.request.close()

break

else:

self.request.sendall((cur_thread.name + ' ' + self.data.upper()).encode('utf-8'))

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):

pass

def client(ip, port, message):

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:

sock.connect((ip, port))

sock.sendall(bytes(message, 'ascii'))

response = str(sock.recv(1024), 'ascii')

print("Received: {}".format(response))

if __name__ == "__main__":

# 如果设置端口为0,则表示任意未被占用端口

HOST, PORT = "localhost", 9000

server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)

ip, port = server.server_address

# 开启该server的一个线程,该线程会为每个请求开启更多的线程

server_thread = threading.Thread(target=server.serve_forever)

# server退出时,终止线程

#server_thread.setDaemon(True)

server_thread.start()

print("Server loop running in thread:", server_thread.name)

# server.shutdown()

# server.server_close()

客户端

#!/usr/bin/env python 3.4.0

#-*- encoding:utf-8 -*-

__author__ = 'shouke'

import socket

import time

if __name__ == '__main__':

if_sock_connected = False

try:

# 创建一个socket (SOCK_STREAM 表示为TCP socket)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到服务器

sock.connect(('localhost', 9000))

# 发送数据

if_sock_connected = True

i = 0

while i < 100:

if i == 6:

sock.sendall(bytes('bye\n', "utf-8"))

else:

sock.sendall(bytes('hello world with tcp\n', "utf-8"))

print("sent data to server:{}".format(bytes('hello world with tcp\n', "utf-8")))

# 从服务器接收数据

received = str(sock.recv(1024), "utf-8")

print('receive data from server:%s' % received)

if received == 'bye':

break

time.sleep(1)

i += 1

except Exception as e:

print('程序运行出错:%s' % e)

finally:

if if_sock_connected:

sock.close()

运行结果

更多资料,烦参考官方文档,socketserver模块。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Mac上自己推送iOS通知到设备

    打开“终端(terminal)”,然后(注意,sudo需要的密码就是系统的root帐号密码)运行“sudo apachectl start”

    用户6094182
  • ElasticSearch必备知识:从索引别名、分词器、文档管理、路由到搜索详解

    如果希望一次查询可查询多个索引。 如果希望通过索引的视图来操作索引,就像数据库库中的视图一样。 索引的别名机制,就是让我们可以以视图的方式来操作集群中的索引...

    数据和云01
  • 使用Docker命令如何启动服务?

    如果出现错误net/http: TLS handshake timeout,将http://d1d9aef0.m.daocloud.io/添加到daemon

    _simple
  • jquery 手风琴效果

    <!doctype html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-eq...

    用户5760343
  • How to use Chrome HAR save HTTP performance

    For performance analysis we would like to archive the detail performance for eac...

    Jerry Wang
  • iOS hosts文件配置

    在开发过程中,可能后端写接口的同学先给你的是本地的地址,让你先测试一遍。那么我们就需要把后端同学电脑的IP地址和对应的域名进行映射。那就需要修改本机的host文...

    用户6094182
  • Centos6.8安装svn 并同步到web

    这些天帮朋友的云服务器配置svn,并要实现svn与web同步,昨天折腾了一天,没有没能折腾出来,不是这里报错就是那里报错了,网上找资料,测试,网上找资料,再测试...

    小海怪的互联网
  • TCP和UDP的区别

    TCP的优点: 可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还...

    葆宁
  • win10下apache superset的使用

    创建虚拟环境: -(1)virtualenv env_supersetobj(创建虚拟环境)

    步履不停凡
  • Java高并发情况下的锁机制优化

    将大对象,拆成小对象,大大增加并行度,降低锁竞争. 如此一来偏向锁,轻量级锁成功率提高.

    大道七哥

扫码关注云+社区

领取腾讯云代金券