python 面向对象编程tcp_Python基础-面向对象-网络传输套接字

本文详细介绍了Python中的Socket编程,包括Socket的基本概念、使用方法,如TCP客户端和服务端的实现,以及UDP通信的示例。还探讨了SocketServer模块,展示了如何创建多线程并发的TCP服务器。此外,还涵盖了TCP和UDP协议下远程执行命令的场景,以及粘包和不粘包特性。
摘要由CSDN通过智能技术生成

socket

简介

socket是应用层与TCP/IP协议通信的中间的软件抽象层,它是一组接口。把复杂的TCP/IP协议足隐藏在接口后面,对用户来说,一组简单的接口就是全部,socket去组织数据,以符合指定的协议

recv在缓冲区为空时,阻塞

recvfrom在缓冲区为空时,接收为空的字节

基于文件的套接字 AF_UNIX

基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在统一机器,可以通过访问同一个文件系统间接完成通信~

基于网络类型的套接字 AF_INET

基于网络作为介质实现通信,还有AD_INET6,被用于ipv6等其它网络类型套接字

示意图

TCP客户端 TCP服务端

socket() socket()

| ↓

| bind()

| ↓

| listen()

↓ ↓

connect() accept()

↓ ↓ 阻塞,直到有客户端连接

write() read()

↓ ↓ 处理请求

read()

↓ ↓

close() ---结束连接--> read()

close()

套接字方法

服务端套接字函数

名称

释义

s.bind()

绑定(主机,端口号)到套接字

s.listen()

开始TCP监听

s.accept()

被动接受TCP客户的连接,(阻塞式)等待连接的到来

客户端套接字函数

名称

释义

s.connect()

主动初始化TCP服务器连接

s.connect_ex()

connect//90函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数

名称

释义

s.recv()

接收TCP数据

s.send()

发送TCP数据(send在待发送数据量大于己端缓存区剩余空间是,数据丢失,不会发完)

s.sendall()

发送完成的TCP数据(本质是循环调用send,待发送数据量大于己端缓存区剩余空间时,数据不会丢失,循环调用send直到发完)

s.recvform()

接收UDP数据

s.sendto()

发送UDP数据

s.getpeername()

连接到当前套接字的远端地址

s.getsockname()

当前套接字地址

s.getsockopt()

返回指定套接字的参数

s.setsockopt()

设置指定套接字的参数

s.close()

关闭套接字

面向锁的套接字方法

名称

释义

s.setblocking()

设置套接字的阻塞与非阻塞模式

s.settimeout()

设置阻塞套接字操作的超时时间

s.gettimeout()

得到阻塞套接字操作的超时时间

面向文件的套接字函数

名称

释义

s.filen()

套接字的文件描述符

s.makefile()

创建一个与该套接字相关的文件

TCP传输套接字

简单示例

服务端

# -*- coding:utf8 -*-

import socket

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

#定义socket通信方式和通信协议。socket.AF_INET基于网络通信,socket.SOCK_STREAM基于TCP协议

test.bind(('127.0.0.1',8000)) #定义通信ID

test.listen(5) #定义最大通信监听数

conn,addr = test.accept() #定义对话连接

msg = conn.recv(1024) #定义接收字节信息

print('客户端发送的消息是:',msg)

conn.send(msg.upper()) #定义发送消息

conn.close() #连接关闭

test.close() #程序关闭

客户端发送的消息是: b'hello'

客户端

# -*- coding:utf8 -*-

import socket

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

#定义socket通信方式和通信协议。socket.AF_INET基于网络通信,socket.SOCK_STREAM基于TCP协议

test.connect(('127.0.0.1',8000)) #定义通信ID,服务器的地址和端口

test.send('hello'.encode('utf-8')) #定义发送内容

data = test.recv(1024) #定义接收字节信息

print('收到服务端的发来的消息是:',data)

收到服务端的发来的消息是: b'HELLO'

TCP网络传输套接字示例

原示例

import socket

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

优化示例

form socket import *

test = socket(AF_INET,SOCK_STREAM)

==也可以将值以变量形式写入到配置文件中导入==

服务端优化示例

# -*- coding:utf8 -*-

from socket import *

test = socket(AF_INET,SOCK_STREAM)

ip_port = ('127.0.0.1',8000)

back_log = 5

buffer_size = 1024

test.bind(ip_port) #定义通信ID

test.listen(back_log) #定义最大通信监听数

conn,addr = test.accept() #定义对话连接

msg = conn.recv(1024) # 定义接收字节信息

print('客户端发送的消息是:',msg)

conn.send(msg.upper()) #定义发送消息

conn.close() #连接关闭

test.close() #程序关闭

循环发送示例

服务端

# -*- coding:utf8 -*-

from socket import *

tcp_servive = socket(AF_INET,SOCK_STREAM)

ip_port = ('127.0.0.1',8000)

back_log = 5

buffer_size = 1024

tcp_servive.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #防止服务端再次启用导致端口被占用错误

tcp_servive.bind(ip_port) #定义通信ID

tcp_servive.listen(back_log) #定义最大通信监听数

while True:

print("服务端程序运行中。。。")

conn, addr = tcp_servive.accept() #定义对话连接(循环收发消息)

while True:

try: #客户端异常断开处理

msg = conn.recv(buffer_size) #定义接收字节信息

print('客户端发送的消息是:',msg.decode('utf-8'))

conn.send(msg.upper()) #定义发送消息

except Exception:

print("客户端强制断开!")

break

conn.close() #连接关闭

tcp_servive.close() #程序关闭

客户端

# -*- coding:utf8 -*-

from socket import *

ip_port = ('127.0.0.1',8000)

buffer_size = 1024

tcp_client = socket(AF_INET,SOCK_STREAM)

tcp_client.connect(ip_port) #定义通信ID,服务器的地址和端口

while True:

msg = input(">>>请输入需要发送的消息!".strip())

if not msg:continue #判断值是否为空

tcp_client.send(msg.encode('utf-8')) #定义发送内容

print('客户端已经发送消息:',msg)

data = tcp_client.recv(buffer_size) #定义接收字节信息

print('收到服务端的发来的消息是:', data.decode('utf-8'))

tcp_client.close()

TCP协议远程执行命令示例

粘包特性

服务端

from socket import *

import subprocess

ip_port = ('127.0.0.1',8080)

back_log = 5

buffer_size = 4096

tcp_server = socket(AF_INET,SOCK_STREAM)

tcp_server.bind(ip_port)

tcp_server.listen(back_log)

while True:

conn,addr=tcp_server.accept() #建立连接

print('新的客户端链接',addr)

while True:

#接收信息

try:

cmd=conn.recv(buffer_size)

if not cmd:break

print('收到客户端的命令',cmd.decode('utf-8'))

#执行命令

res=subprocess.Popen(cmd.decode('utf-8'),shell=True,

stderr=subprocess.PIPE,

stdout=subprocess.PIPE,

stdin=subprocess.PIPE)

err=res.stderr.read()

if err:

cmd_res=err

else:

cmd_res=res.stdout.read()

#发送信息

if not cmd_res:

cmd_res='执行成功'.encode('gbk')

conn.send(cmd_res)

except Exception as e:

print(e)

break

客户端

from socket import *

ip_port = ('127.0.0.1',8080)

back_log = 5

buffer_size = 4096

tcp_client = socket(AF_INET,SOCK_STREAM)

tcp_client.connect(ip_port)

while True:

cmd=input('>>请输入需要执行的命令: ').strip()

if not cmd:continue

if cmd == 'quit':break

tcp_client.send(cmd.encode('utf-8'))

cmd_res=tcp_client.recv(buffer_size)

print('命令的执行结果是 ',cmd_res.decode('gbk'))

tcp_client.close()

UDP网络传输套接字

简单示例

服务端

udp_service = socket() #创建一个服务器套接字

udp_service.bind() #绑定服务器套接字

while True: #服务器通讯循环

udp_service.recvfrom() #服务端接收消息

udp_sendto.recvfrom() #服务端发送消息

udp_service.close() #关闭服务端套接字

客户端

udp_client = socket() #创建一个客户端套接字

while True: #客户端通讯循环

udp_service.recvfrom() #服务端接收消息

udp_sendto.recvfrom() #服务端发送消息

udp_client.close() #关闭客户端套接字

UDP网络传输套接字示例示例

服务端示例

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

from socket import *

ip_port = ('127.0.0.1',8080) #定义通信ID

buffer_size = 4096 #定义接收字节信息

udp_service = socket(AF_INET,SOCK_DGRAM) #定义socket通信方式和通信协议。socket.AF_INET基于网络通信,socket.SOCK_STREAM基于TCP协议

udp_service.bind(ip_port) #通信ID

print("服务端运行中...")

while True:

msg,addr = udp_service.recvfrom(buffer_size) #定义接收字节信息(元组形式)

print("接收到的消息是:",msg.decode('utf-8')) #打印接受到的字节信息

udp_service.sendto(msg.upper(),addr) #返回并修改传输值

客户端示例

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

from socket import *

ip_port = ('127.0.0.1',8080) #定义通信ID

buffer_size = 4096 #定义接收字节信息

udp_client = socket(AF_INET,SOCK_DGRAM) #定义socket通信方式和通信协议。socket.AF_INET基于网络通信,socket.SOCK_STREAM基于TCP协议

while True:

msg = input(">>>请输入您要发送的内容".strip())

udp_client.sendto(msg.encode('utf-8'),ip_port) #定义发送内容和到达地址

msg,addr = udp_client.recvfrom(buffer_size) #定义接收字节信息(元组形式)

print(msg.decode('utf-8')) #打印返回的字节信息

UDP协议远程执行命令示例

不粘包特性

服务端

from socket import *

import subprocess

ip_port=('127.0.0.1',8080)

back_log=5

buffer_size=4096

udp_server=socket(AF_INET,SOCK_DGRAM)

udp_server.bind(ip_port)

while True:

#接收消息

cmd,addr=udp_server.recvfrom(buffer_size)

# 执行命令,得到命令的运行结果cmd_res

res = subprocess.Popen(cmd.decode('utf-8'), shell=True,

stderr=subprocess.PIPE,

stdout=subprocess.PIPE,

stdin=subprocess.PIPE)

err = res.stderr.read()

if err:

cmd_res = err

else:

cmd_res = res.stdout.read()

if not cmd_res:

cmd_res='执行成功'.encode('gbk')

#发送消息

udp_server.sendto(cmd_res,addr)

客户端

from socket import *

ip_port=('127.0.0.1',8080)

back_log=5

buffer_size=4096

udp_client=socket(AF_INET,SOCK_DGRAM)

while True:

cmd=input('>>请输入需要执行的命令: ').strip()

if not cmd:continue

if cmd == 'quit':break

udp_client.sendto(cmd.encode('utf-8'),ip_port)

cmd_res,addr=udp_client.recvfrom(buffer_size)

print('命令的执行结果是 ',cmd_res.decode('gbk'),end='')

udp_client.close()

SocketServer

简介

socketserver 是标准库中一个高级别的模块,用于简化网络客户与服务器的实现。

1、要实现本模块,必须定义一个继承于基类BaseRequestHandler的处理程序类。BaseRequestHandler类的实例可以实现以下方法:

> h.handle()

调用该方法执行实际的请求操作。调用该函数可以不带任何参数,但是几个实例变量包含有用的值。h.request包含请求,h.client_address包含客户端地址,h.server包含调用处理程序的实例。对TCP之类的数据流服务,h.request属性是套接字对象。对于数据报服务,它是包含收到数据的字节字符串。

> h.setup()

该方法在handle()之前调用。默认情况下,它不执行任何操作。如果希望服务器实现更多连接设置,可以在这里实现。

> h.finish()调用本方法可以在执行完handle()之后执行清除操作。如果setup()和 handle()都不生成异常,则无需调用该方法。

2、服务器。要使用处理程序,必须将其插入到服务器对象。定义了四个基本的服务器类。

1、TCPServer 支持ipv4的TCP协议的服务器。

2、UDPServer 支持ipv4的UDP协议的服务器。

3、UnixStreamServer 使用UNIX域套接字实现面向数据流协议的服务器,集成自TCPserver。

4、UnixDatagramServer 继承自UDPServer

四个服务器类的实例都有一下方法和变量:

1、s.socket 用于传入请求的套接字对象

2、s.server_address 监听服务器的地址

3、s.RequestHandleClass 传递给服务器构造函数并由用户提供的请求处理程序类

4、s.server_forever() 处理无线的请求

5、s.shutdown() 停止server_forever()循环

6、s.fileno() 返回服务器套接字的整数文件描述符。该方法可以有效的通过轮询操作实例

SocketServer简单示例

import socketserver

class 自定义类(socketserver.BaseRequestHandler):

def handle(self):

pass

socketserver.ThreadingTCPServer((),自定义类)

s.server_forever

SocketServer TCP多线程并发实例

服务端

# -*- cond:utf8 -*-

import socketserver #导入多并发模块

class MyServer(socketserver.BaseRequestHandler):

def handle(self):

print('conn is: ',self.request) #conn

print('addr is: ',self.client_address) #addr

while True:

try:

#收消息

data=self.request.recv(1024)

if not data:break

print('收到客户端的消息是',data,self.client_address)

#发消息

self.request.sendall(data.upper())

except Exception as e:

print(e)

break

if __name__ == '__main__':

s=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer) #多线程

print('服务运行中...')

s.serve_forever()

客户端(允许多个一样的客户端)

from socket import *

ip_port=('127.0.0.1',8080)

back_log=5

buffer_size=1024

tcp_client=socket(AF_INET,SOCK_STREAM)

tcp_client.connect(ip_port)

while True:

msg=input('>>请输入您要发送的内容: ').strip()

if not msg:continue

if msg == 'quit':break

tcp_client.send(msg.encode('utf-8'))

data=tcp_client.recv(buffer_size)

print('收到服务端发来的消息:',data.decode('utf-8'))

tcp_client.close()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值