美文网首页一个程序员自学中
使用python搭建Socket服务器

使用python搭建Socket服务器

作者: 小船翻不翻 | 来源:发表于2020-06-27 21:31 被阅读0次

    #coding utf-8

    import socket全双工

    
    socket.AF_INET  #IPv4版本
    socket.SOCK_DGRAM    #是udp
    socket.SOCK_STREAM    #是tcp
    #设置当服务器先close 保证下次运行程序可以立即使用端口
    .setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    

    3次握手操作

    1. 客户端发起链接syn
    2. 服务器回应ack并发起syn
    3. 客户端回应ack

    4次挥手操作,一般由客户端发起关闭

    1. 客户端发起关闭‘发送’
    2. 服务器回应接收到
    3. 服务器发起关闭‘接收’
    4. 客户端回应接收到,并等待一段时间(2-5min)释放资源,又叫2msl两倍等待释放
    • udp不区分服务器与客户端
      socket 创建套接字
      bind 绑定IP和port
      sendto/recvfrom 发送/接收数据.recvfrom(1024)如果没有数据会造成阻塞
      close 关闭套接字

    • tcp客户端
      socket 创建套接字
      connect 链接服务器
      send/recv 发送/接收数据
      close 关闭套接字

    • tcp服务器
      socket 创建套接字
      bind 绑定IP和port
      listen 被动接收模式
      accept 接收客户端链接地址
      recv/send 接收/发送数据
      close 关闭套接字

    .listen(128) 被动模式 128代表同一时间可以处理的链接数量
    .accept() 接收数据

    字符串前面添加b就可以转化成字节,如:b‘hhhsdf’
    变量.encode("utf-8") 转化任意编码成字节,如:abc.encode("utf-8")
    Windows默认使用gbk编码发送消息

    socket模拟服务器处理响应

    所有的linux里面的东西都对应一个文件
    fd文件描述符,就是一个数字,对应一个特殊的文件,例如网络接口

    • 主进程中等待socket,启用进程处理链接的同时应当继续调用socket.close();多线程/协程都不需要在主线程中调用socket.close()
    • socket.setblocking(False)设置套接字为非堵塞的方式
    #非阻塞链接
    tcp_server = socket(···)
    tcp_server.setblocking(False)  # 设置套接字为非堵塞的方式
    client_socket_list = list()
    while True:
        try:
            new_socket, new_address = tcp_server.accept()
        except Exception as ret:
            print(“——-没有新的客户的客户端到来——”)
        else:
            print(“—-只要没有异常,那么就意味着 来了一个新的客户大u呢——-”)
            new_socket.setblocking(False)
            client_socket_list.append(new_socket)
        for client_socket in client_socket_list:
            try:
                recv_data = client_socet.recv(1024)
            except Exception as ret:
                print(“——这个客户端没有发送过来数据——”)
            else:
                if recv_data:
                    print(“——客户端发送过来了数据——”)
                else:
                    client_socket.close()
                    client_socket_list.remove(client_socket)
    
    • 处理客户端请求数据的响应中增加Content-Length:body内容长度来告诉浏览器资源响应完毕,实现长链接

    常用Linux命令

    ps -aux查看所有进程
    kill 进程ID可以杀死指定进程
    sudo dhclient 管理员桥接网络设置,将虚拟机IP网段与本机保持一致
    mkdir 文件夹 创建目录
    touch 文件名 创建指定文件名的文件
    ls 查看当前目录下的文件或文件夹
    ls -a 包含隐藏文件.开头的文件就是隐藏的
    cp 当前文件 目标文件 拷贝当前文件到目标文件(自动创建目标文件)
    mv修改目标文件名称
    cat查看指定文件内容
    tail -f持续查看文件内容

    常用方法

    1. 在方法中修改全部变量时,如果使用赋值= ,需要在方法中提前声明 global变量
    2. print("\r拷贝进度:%.2f" % (2*100/123),end="")实现单行输出
    3. help(对象名)获取对象帮助信息
    4. range(10)自动生成10以内列表

    from collections import Iterator/Iterable迭代器

    from collections import Iterable
    isinstance(验证对象,Iterable)返回True表示可以迭代

    特性/伪协程

    • 节省内存空间,因为不会立刻计算
    • [x*2 for x in range(10)]只是列表(x*2 for x in range(10))这样返回的就是一个可迭代对象
    • 包含yield方法就会变成迭代,执行一部分就直接返回数据
    • 可以暂停代码,在yield语句位置
    • form greenlet import greenlet封装来yield的实现greenlet(普通方法名)方法中不再需要出现yield实现协程效果
    1. 一个普通对象如果要实现迭代功能需要实现:def __iter__(self):返回自身;def __next__(self):返回每次要取的值
    2. raise StopIteration结束迭代
    3. next(对象)获得下一个值
    4. .send(参数)可迭代中修改对象的返回值,需要在next后使用,否则参数只能是None

    import multiprocessing进程

    1. .Process 创建进程对象
    2. .Queue创建队列,.put()添加数据,.get()获取一条数据没有会等待,.get_nowait()不等待取数据,.full()队列是否满了,.empty()队列是否空了
    3. .Pool(3)定义一个进程池,.apply_async( 方法名,参数)空闲子进程调用方法,.join()等待close后 结束进程池
    4. .Manager().Queue()可传递到进程池

    import threading线程

    1. threading.Thread(target=方法名,args=参数)将指定方法添加到多任务中,参数是元组
    2. .start()开始执行多任务
    3. .enumerate()获得已有线程列表
    4. .Lock()创建线程锁,返回锁对象 .acquire()上锁,.release()解锁

    import gevent协程

    只有遇到延时操作会自动切换协程,否则只会顺序执行
    geven是对 greenlet的封装,greenlet是对yield的封装

    1. gevent.spawn(方法,方法参数)创建一个协程对象
    2. gevent.getcurrent()获得当前运行的协程对象
    3. gevent.sleep(1)休息一秒
    4. .join() 等待协程运行gevent.joinall([gevent对象])多个等待
    5. gevent.monkey.patch_all()程序中用到time语法的耗时操作,转换成gevent中自己实现的模块

    import os 文件操作

    1. .mkdir创建文件夹
    2. .listdir获得文件夹下的所有文件列表
    3. with open('','wb') 保证文件会自动关闭

    import urllib网络请求

    1. urllib.request.urlopen(‘网址’).read()获得响应数据流

    import re正则

    通用正则

    字符 功能
    . 匹配任意1个字符(除了\n)
    [] 匹配[]中列举的字符
    \d 匹配数字0-9
    \D 匹配非数字
    \s 匹配空白 空格 tab键
    \S 匹配非空白
    \w 匹配单词字符a-z A-Z 0-9 _ 汉字
    \W 匹配非单词字符
    —- 多次匹配⬇️
    * 匹配前一个字符出现0或无限次
    + 匹配前一个字符出现1或无限次
    ? 匹配前一个字符出现1或0次
    {m} 匹配前一个字符出现m次
    {m,n} 匹配前一个字符出现从m到n次
    —— 开始结束⬇️
    ^ 匹配字符串开始
    $ 匹配字符串结尾
    匹配分组⬇️
    匹配左右任意一个字符
    (abc) 将括号中字符作为一个分组
    \num 引用分组num匹配到的字符串
    (?p<name>) 分组起别名
    (?p=nam) 引用别名为name分组匹配到的字符串
    1. [a-zA-Z0-9_]{4,20}@163\.com$一个邮箱正则,大小写字母数字下划线 长度4-20 @163.com结尾
    2. <(\w*)>.*</\1>\num的用法\1代表前面分组中的值如<h1></h1>

    re模块高级用法

    1. re.match(r”正则”,用户输入多字符串或列表)获得所有匹配对象
    2. re.search(r”正则”,字符串或列表)匹配到就结束
    3. .group()返回所有匹配值
    4. re.findall()搜索所有匹配 列表
    5. re.sub(r正则,替换值,用户输入字符串)将匹配到的数据进行替换,返回替换后的值;替换值可以是一个函数
    6. re.split(r”:| ”,用户输入的字符串)使用冒号或空格切割并返回一个列表

    import random随机

    .choice(列表)随机获取一个值

    相关文章

      网友评论

        本文标题:使用python搭建Socket服务器

        本文链接:https://www.haomeiwen.com/subject/slputctx.html