zoukankan      html  css  js  c++  java
  • web----Socket

     Socket:

    简单Socket连接,同步请求

    Tcp

    服务端

    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #基于Tcp的数据流
    #sk.setblocking(False)                                 #非堵塞IO,好像每次开启服务器只能产生一个socket,如果socket不断开,被人机器连接不上
                                     #如果设置False,那么accept和recv时一旦无数据,则报错。需要try(异常处理)
    sk.bind(ip_port) sk.listen(backlog) #backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5
          这个值不能无限大,因为要在内核中维护连接队列
    while True: print('server waiting...') conn,addr = sk.accept() print(conn) client_data = conn.recv(1024) #一次接受1024字节,如果没有接受完,会粘包 print(client_data.decode("utf8")) conn.sendall(bytes('已经收到消息',encoding="utf8")) conn.close()

    客服端

    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.connect(ip_port)
    data = input("输入数据")
    sk.sendall(bytes(data,encoding="utf8"))
    server_reply = sk.recv(1024)
    print(server_reply.decode("utf8"))
    sk.close()

     异步请求非堵塞

    客服端

    import socket
    import select
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
    sk.setblocking(False)           
    sk.bind(ip_port)
    sk.listen(1)                     
    inputs = []
    inputs.append(sk)
    print('server waiting...')
    while True:
        rlist,wlist,elist = select.select(inputs,[],[],0.05)  #利用select监听socket 和 conn
        for i in rlist:
            if i ==sk:
                conn,addr = sk.accept()
                conn.setblocking(False)
                inputs.append(conn)
                print(conn)
            else:
                try:
                    client_data = i.recv(1024)                      #一次接受1024字节,如果没有接受完,会粘包
                    print(client_data.decode("utf8"))
                    i.sendall(bytes('已经收到消息',encoding="utf8"))
                except Exception as e:
                    print("客户端终止请求")
                    i.close()
                    inputs.remove(i)
                    continue

    客户端

    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.connect(ip_port)
    while True:
        data = input("输入数据")
        sk.sendall(bytes(data, encoding="utf8"))
        server_reply = sk.recv(1024)
        print(server_reply.decode("utf8"))

     UDP:

    服务端

    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
    sk.bind(ip_port)
    
    while True:
        data,addr = sk.recvfrom(1024)   #不需要三次握手(不需要连接),直接接受数据
        print(data)
        sk.sendto(b"nihao",addr)        #通过接受来的ip地址进行发数据

    客户端

    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
    while True:
        data = input("输入数据").strip()
        inp = data.encode("utf8")
        sk.sendto(inp,ip_port)              #直接往服务器的ip地址,发消息
        data,addr = sk.recvfrom(1024)       #直接接受服务器的数据
        print(data,addr)

     SocketServer模块:

    SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。

                                                 

    ThreadingTCPServer

    ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互。

    使用ThreadingTCPServer:

    • 创建一个继承自 SocketServer.BaseRequestHandler 的类
    • 类中必须定义一个名称为 handle 的方法
    • 启动ThreadingTCPServer
    服务端
    import
    socketserver #在python2.X 叫SocketServer class MyServer(socketserver.BaseRequestHandler): def handle(self): conn = self.request conn.sendall(bytes("已连接",encoding="utf8")) while True: data = conn.recv(1024) print(data.decode("utf8")) conn.sendall(data) if __name__ == '__main__': server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyServer) server.serve_forever()
    客户端
    import
    socket ip_port = ('127.0.0.1',8009) sk = socket.socket() sk.connect(ip_port) # sk.settimeout(5) print(sk.recv(1024).decode("utf8")) while True: inp =input("请输入") sk.sendall(inp.encode("utf8")) data = sk.recv(1024) print(data.decode("utf8"))

    内部调用流程为:

    • 启动服务端程序
    • 执行 TCPServer.__init__ 方法,创建服务端Socket对象并绑定 IP 和 端口
    • 执行 BaseServer.__init__ 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 MyRequestHandle赋值给self.RequestHandlerClass
    • 执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ...
    • 当客户端连接到达服务器
    • 执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
    • 执行 ThreadingMixIn.process_request_thread 方法
    • 执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass()  即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用 MyRequestHandler的handle方法)
    简单版源码   多线程 + select 将request交给线程进行处理,select用来监听是否有请求连接
    import socket
    import threading
    import select
    def process(request, client_address):
        print(request,client_address)
        conn = request
        conn.sendall(bytes("欢迎致电 10086,请输入1xxx,0转人工服务.",encoding="utf8"))
        flag = True
        while flag:
            data = conn.recv(1024)
            if data == 'exit':
                flag = False
            elif data == '0':
                conn.sendall(bytes("通过可能会被录音.balabala一大推",encoding="utf8"))
            else:
                conn.sendall(bytes('请重新输入.',encoding="utf8"))
    sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.bind(('127.0.0.1',8888))
    sk.listen(5)
    while True:
        r, w, e = select.select([sk,],[],[],1)
        print('looping')
        if sk in r:
            print('get request')
            request, client_address = sk.accept()
            t = threading.Thread(target=process, args=(request, client_address))
            t.daemon = False
            t.start()
    sk.close()
  • 相关阅读:
    反射创建对象
    DevExpress 日期输入框
    SsdlToSql10.tt文件内容
    ExecuteNonQuery requires an open and available Connection. The connection's current state is closed.
    DevExpress XtraCharts 图表导出PDF/XLS/JPEG
    Java中堆内存和栈内存详解(转)
    批量合并word文档
    java内部类总结(转)
    Java 之工厂方法和抽象工厂模式(转)
    Java GC 、引用
  • 原文地址:https://www.cnblogs.com/yanxiaoge/p/10501576.html
Copyright © 2011-2022 走看看