python10-socket

socket网络编程

  • socket基于tcp、ip协议的工具
  • 所有的网络通信都基于socket
    • wanghzh/p/5560787.html
    • wupeiqi/articles/5040823.html
  • 客户端去访问服务器:
    • TCP:三次握手
    • UDP:单向访问
    • python支持unix系统进程与进程之间的通信

自己实现socket客户端和服务端

socket服务端
import socket

sk = socket.socket()  # 服务器启动,创建socket
ip_port = ('127.0.0.1', 9999)
sk.bind(ip_port)  # socket绑定ip和端口作为服务端
sk.listen(5)  # socket服务器支持连接等待的数量

while True:
    sock, addr = sk.accept()  # 阻塞等待客户端访问
    sock.sendall(bytes('已链接到服务器', encoding='utf-8'))
    print(type(sock))
    while True:
        try:
            byte_data = sock.recv(1024) # 客户端如果断开了,这里会报异常
            data = str(byte_data, encoding='utf-8')
            ret = '服务器:%s' % data
            sock.sendall(bytes(ret, encoding='utf-8'))
            if data == 'q':
                break
        except Exception as e:
            break
        else:
            pass
        finally:
            pass
socket客户端
import socket

client = socket.socket()  # 创建socket
client.connect(('127.0.0.1', 9999,))  # socket去连接服务端
byte_data = client.recv(1024)
print(str(byte_data, encoding='utf-8'))
while True:
    inp = input()
    client.sendall(bytes(inp, encoding='utf-8'))
    byte_data = client.recv(1024)
    data = str(byte_data, encoding='utf-8')
    if data == '服务器:q':
        print('断开连接')
        break
    else:
        print(data)
client.close()
  • socket.sendall()方法在python2.7中接收字符串,在python3.x中接收ude是字节

socket更多方法

  • wupeiqi/articles/5040823.html
sk = socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM,proto=0)
# family:socket.AF_INET = IPv4(默认) IPv6
# type:TCP协议
# proto:默认为0
sk.bind((ip,port,)
# 服务端绑定IP和port
sk.listen(count)
# 开始监听,参数表示最多等待的数量,当count == 2
# 一个客户端连上了服务器,如果再有2个客户端访问,后面的2个会处于等待状态,当再有客户端访问,超过count == 2的客户端会报错
sk.setblocking(bool)
# 是否阻塞
# True:阻塞(默认)
# False:不阻塞,当socket调用recv和accept时会报错,以后会用到
sk.connect((ip,port,)
# 客户端连接服务端
sk.connect_ex((ip,port,)
# 同上,只是如果连接上,则返回0,如果连不上,返回错误码
sk.close()
# 断开连接
sk.recv(1024)
# 接收信息,参数表示一次最所接收多少个字节
sk.recvfrom(buffersize)
# 从哪里接收UPD用到
sk.send()
# 发送信息,2.7中接收字符串,3.x中接收字节
# send方法有个弊端,实际发送的数据会出现少于实质传入的数据
sk.sendall()
# 底层通过循环和send方法发送数据,不会出现数据丢失
sk.sendto()
# 针对UDP
sk.settimeout()
# 设置超时
sk.getsocketname()
# 返回socket自己的地址
sk.getpeername()
# 返回socket连接远程的地址
sk.fileno()
# socket的文件描述(后面会用到)

socket实现文件上传

  • 注意防止粘包问题
server
import socket

server = socket.socket()
server.bind(('127.0.0.1', 9999))
server.listen(5)
print('服务器启动:\n>>>>>')

while True:
    conn,address = server.accept()
    print('获取到客户端访问:ip:%s port:%s'%(address[0], address[1]))
    retStr = '文件上传服务器,请发送文件名以及文件大小'
    conn.sendall(bytes(retStr, encoding='utf-8'))
    fileInfo = conn.recv(1024)
    fileInfo = str(fileInfo, encoding='utf-8')
    fileName, fileLength = fileInfo.split('&')
    print('获取到文件名:%s 文件大小:%s'%(fileName,fileLength))
    conn.sendall(bytes('接收成功',encoding='utf-8'))
    totalLength = int(fileLength)
    hasLoadSize = 0
    file = open(fileName, mode='wb')
    while True:
        if hasLoadSize >= totalLength:
            break
        data = conn.recv(1024)
        file.write(data)
client
import socket
import os
client = socket.socket()
client.connect(('127.0.0.1', 9999))

connectInfo = client.recv(1024)
connectInfo = str(connectInfo, encoding='utf-8')
print(connectInfo)
fileName = input('请输入文件名\n>>> ')
fileLength = os.stat('dest_top_img.jpg').st_size
ret_msg = '%s&%s'%(fileName,fileLength)
client.sendall(bytes(ret_msg, encoding='utf-8'))
rec_msg = client.recv(1024)
print(str(rec_msg, encoding='utf-8'))
print(str(rec_msg, encoding='utf-8'))
with open('dest_top_img.jpg', mode='rb') as file:
    for line in file:
        client.sendall(line)
client.close()
  • 粘包原因:
    • 报错:ImageNotLoaded(下载完后打不开文件)
    • 客户端发送文件到服务端,需要依赖系统的缓冲区
    • 服务端接收客户端发送的文件,需要到缓冲区取
    • 但是客户端缓冲区什么时候发送是系统决定的,不可控,可能存在这种情况,当发送文件名和文件大小给服务器的时候,数据存放在缓冲区还没发送出直接发送文件内容,当服务端获取文件和文件大小的字段带有一部分文件的内容,这就导致需要发送的文件到服务器实际接收的时候不完整
    • 解决:发送文件名、大小和发送文件之间与服务器做一个响应

socketserver模块实现多并发

  • socket模块不支持多并发,服务端同一时刻只支持响应一个客户端请求
  • 处理并发有两种方式:
    • IO多路复用

    • socketserver模块:由python提供的另一个模块,用于解决多并发访问的问题

      • 内部实现:IO多路复用&多线程或多进程并发操作
    • 实现步骤:

      • 创建类继承:socketserver.BaseRequestHandler
      • 创建server,传入ip端口和刚创建的类
      • 开启服务
```
import socketserver

class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        print(self.request) # 客户端的连接
        print(self.client_address) # 客户端地址
        print(self.server) # 当前服务器:server

if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',9999),MyServer)
    server.serve_forever()
# <socket.socket fd=520, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 4971)>
# ('127.0.0.1', 4971)
# <socketocketserver.ThreadingTCPServer object at 0x00FAB310>
```

```
import socket
client = socket.socket()
client.connect(('127.0.0.1',9999))
```

梳理

  • 对象中封装对象
  • 面向对象的两种特性
    • 装饰器 + 方法
    • @property + 方法
  • python2.7继承流程
    • 继承object类(新式类):顶部最后
    • 未继承object类(经典类):一条道走到黑,深度优先
  • python3.x继承流程
    • 顶部最后
  • 抽象类和抽象方法(python中目前用的不多)
    • 约束
    • 接口(python没有接口)
    • 抽象类+抽象方法
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,593评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,418评论 25 707
  • 昨晚微信上有个东北的小姑娘失眠,她说大叔既然睡不着,一起谈谈人生呗。 我回她说:"男人和女人的人生观差别太大,谈不...
    令狐大葱阅读 288评论 0 0
  • 妈妈告诉我,八婶可能活不了几天了,子宫癌晚期。当我听到这个消息的时候异常的震惊,我记得4月份回家的时候,她还好好的...
    向行阅读 301评论 8 3
  • “活着是为了给过去的自己看的” 有时候突发奇想,我会想象着自己如果回到过去面对当年那个为什么事都烦恼的自己,会是怎...
    灯灯_阅读 361评论 0 0