zoukankan      html  css  js  c++  java
  • web框架之socket

    概述

      套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(又名一个进程)与另一个运行的程序进行通信。这就是所谓的进程间通信 ( Inter Process Communication,IPC)。有两种类型的套接字:基于文件的和面向网络的。
      UNIX 套接字是我们所讲的套接字的第一个家族,并且拥有一个“家族名字” AF_UNIX(又名 AF_LOCAL,在 POSIX1.g 标准中指定),它代表地址家族( address family): UNIX。包括 Python 在内的大多数受欢迎的平台都使用术语地址家族及其缩写 AF。
      第二种类型的套接字是基于网络的,它也有自己的家族名字 AF_INET,或者地址家族:因特网。在所有的地址家族之中,目前 AF_INET 是使用得最广泛的。
      总的来说, Python 只支持 AF_UNIX、 AF_NETLINK、 AF_TIPC 和 AF_INET 家族。

      而web的重点就是AF_INET这个家族。

    socket模块

    • 要创建套接字,必须使用 socket.socket()函数,它一般的语法如下。
    socket(socket_family, socket_type, protocol=0)

    ps:socket_family 是 AF_UNIX 或 AF_INET (如前所述),socket_type 是 SOCK_STREAM或 SOCK_DGRAM(也如前所述)。 protocol 通常省略,默认为 0。

    • 创建 TCP/IP 套接字。
    tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    • 创建 UDP/IP 套接字。
    udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    套接字对象方法:

    示例

    TCP实例:

      这是一个简单的server<--->client复读机的小实例:

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    import socket
    
    #创建socket对象
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #将地址(ip,port)绑定到套接字上
    sock.bind(("localhost",8000))
    #设置并开启tcp监听器
    sock.listen(5)
    while True:
        #被动接受tcp客户端连接,一直等待直到连接到达(阻塞)
        connection,addr = sock.accept()
        #当有连接进来,先给对方发送一个数据
        connection.sendall("我是所有web框架的元祖,有什么要说的么?")
        flag =True
        while flag:
            # 设置一次性接受数据的最大单元,并保存至data
            data = connection.recv(1024)
            print data
            if data == "exit":
                flag = False
            else:
                connection.sendall(data)
        #关闭连接
        connection.close()
    server
    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    import socket
    #创建对象
    sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #建立连接
    sk.connect(("127.0.0.1",8000))
    #尝试5秒,连接失败
    sk.settimeout(5)
    while True:
        #接受server端发送的数据,每次最大为1024字节
        data = sk.recv(1024)
        print "SocketServer: %s"%data
        msg = raw_input("Input:")
        sk.sendall(msg)
        if msg == "exit":
            break
    sk.close()
    client

    结果演示:

    socketServer显示:

    无敌了我的哥!
    你复读机啊
    还真TM是复读机
    exit

    socketClient与socketServer交互界面:

    SocketServer: 我是所有web框架的元祖,有什么要说的么?
    Input:无敌了,我的哥!
    SocketServer: 无敌了我的哥!
    Input:你复读机啊
    SocketServer: 你复读机啊
    Input:还真TM是复读机
    SocketServer: 还真TM是复读机
    Input:exit
    
    Process finished with exit code 0

     UDP实例

    Socket服务器通用伪代码

    虽说一图顶前言,不过还是要简单的来个通用模板,以防自己脑袋秀逗了,哈哈!!

    TCP服务器通用伪代码

    ss = socket()              # 创建服务器套接字
    ss.bind()                 # 套接字与地址绑定
    ss.listen()               # 监听连接
    while True:               # 服务器无限循环
        conn,addr = ss.accept()      # 接受客户端连接
            while True:           # 通信循环
                conn.recv()/conn.send() # 对话(接收/发送)
        conn.close()                 # 关闭通话连接
    ss.close()                # 关闭服务器套接字#(可选)

    ps:这个服务器模型是有缺陷的,一次只能处理一个连接请求,SocketServer模块可以实现多并发。(下文摘自《python核心编程》帮助理解此模板)

      ss.accept接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。addr是连接客户端的地址。接收TCP 客户的连接(阻塞式)等待连接的到来.

      所有套接字都是通过使用 socket.socket()函数来创建的。因为服务器需要占用一个端口并等待客户端的请求,所以它们必须绑定到一个本地地址。因为 TCP 是一种面向连接的通信系统,所以在 TCP 服务器开始操作之前,必须安装一些基础设施。特别地, TCP 服务器必须监听(传入)的连接。一旦这个安装过程完成后,服务器就可以开始它的无限循环。

      调用 accept()函数之后,就开启了一个简单的(单线程)服务器,它会等待客户端的连接。默认情况下, accept()是阻塞的,这意味着执行将被暂停,直到一个连接到达。这里不展开非阻塞情况。

      一旦服务器接受了一个连接,就会返回(利用 accept())一个独立的客户端套接字,用来与即将到来的消息进行交换。使用新的客户端套接字类似于将客户的电话切换给客服代表。当一个客户电话最后接进来时,主要的总机接线员会接到这个电话,并使用另一条线路将这个电话转接给合适的人来处理客户的需求。

      这将能够空出主线(原始服务器套接字),以便接线员可以继续等待新的电话(客户请求),而此时客户及其连接的客服代表能够进行他们自己的谈话。同样地,当一个传入的请求到达时,服务器会创建一个新的通信端口来直接与客户端进行通信,再次空出主要的端口,以使其能够接受新的客户端连接。

      一旦创建了临时套接字,通信就可以开始,通过使用这个新的套接字,客户端与服务器就可以开始参与发送和接收的对话中,直到连接终止。当一方关闭连接或者向对方发送一个空字符串时,通常就会关闭连接。

      在代码中,一个客户端连接关闭之后,服务器就会等待另一个客户端连接。最后一行代码是可选的,在这里关闭了服务器套接字。其实,这种情况永远也不会碰到,因为服务器应该在一个无限循环中运行。在示例中这行代码用来提醒读者,当为服务器实现一个智能的退出方案时,建议调用 close()方法。例如,当一个处理程序检测到一些外部条件时,服务器就应该关闭。在这些情况下,应该调用一个 close()方法。

    TCP客户端通用伪代码

    cs = socket()              # 创建客户端套接字
    cs.connect()               # 尝试连接服务器
    while True:               # 通信循环
        cs.send()/cs.recv()   # 对话(发送/接收)
    cs.close()                  # 关闭客户端套接字

    SocketServer模块

      通过SocketServer模块,实现多线程,同时处理多个请求:

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    import SocketServer
    
    class Myserver(SocketServer.BaseRequestHandler):
    
        def handle(self):
            conn = self.request
            print self.client_address
            conn.sendall("我能同时处理多个请求!")
            flag = True
            while flag:
                data = conn.recv(1024)
                if data == "exit":
                    flag = False
                else:
                    conn.sendall(data)
    
    if __name__ == "__main__":
        server = SocketServer.ThreadingTCPServer(("localhost",8000),Myserver)
        server.serve_forever()
  • 相关阅读:
    bootstrapValidator表单验证插件
    sublime自动保存(失去焦点自动保存)
    js、jquery实现放大镜效果
    mysql 添加索引语句
    mybatis sql语句中的foreach标签
    android ListView 刷新卡顿问题
    JFrame 桌面右下角弹窗
    取没有date的邮件发送时间
    java 判断图片是否损坏
    java 后台poi导入导出Excel到数据库
  • 原文地址:https://www.cnblogs.com/chbo/p/6955697.html
Copyright © 2011-2022 走看看