美文网首页
python关于Socket编程方法

python关于Socket编程方法

作者: 叶扬风起 | 来源:发表于2019-07-25 21:15 被阅读0次
    socket
    1、创建

    socket.socket(family=AF_INET, type=SOCK_STREAM, protocal=0)

    • socket families(地址簇):
       AF_UNIX :unix本机之间进行通信
       AF_INET :使用IPv4
       AF_INET6 :使用IPv6
    • socket types:
       SOCK_STREAM :TCP套接字类型
       SOCK_DGRAM :UDP套接字类型
       SOCK_RAW :原始套接字类型,这个套接字比较强大,创建这种套接字可以监听网卡上的所有数据帧
       SOCK_RDM :是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。

    注:这些常量都是套接字类型,应用于socket()函数中的第二个参数中.根据系统的不同,可能有更多的常数。(只有SOCK_STREAMSOCK_DGRAM似乎通常很有用。

    • protocal:
        协议号通常为零,可以省略,或者在地址族为AF_CAN的情况下,协议应为CAN_RAWCAN_BCM 。如果指定fileno,则忽略其他参数,从而导致具有指定文件描述器的套接字返回。
        与socket.fromfd()不同,fileno将返回相同的套接字,而不是重复。这可能有助于使用socket.close()关闭分离的套接字,一般情况下后两个参数忽略即可
    #创建 TCP/IP 套接字
    tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #创建 UDP/IP 套接字
    udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    2. TCP Socket通信

    如下图所示,TCP通信的基本步骤如下:
    服务端:socket---bind---listen---while(True){---accept----recv---send---}---close
    客户端:socket----------------------------------------connect---send---recv-------close


    TCP Socket通信
    • 创建
    socket.socket([family[, type[, proto]]])
        family : AF_INET (默认ipv4), AF_INET6(ipv6) or AF_UNIX(Unix系统进程间通信)
        type : SOCK_STREAM (TCP), SOCK_DGRAM(UDP) .
        protocol : 一般为0或者默认
    

    如果socket创建失败会抛出一个socket.error异常</code>

    • 服务器函数
      1). bind函数
        使服务器的这个端口和IP处于监听状态,等待网络中某一客户机的连接请求。如果客户端有连接请求,端口就会接受这个连接。
    s.bind(address)
        s为socket.socket()返回的套接字对象
        address为元组(host,port)
            host: ip地址, 为一个字符串
            post: 自定义主机号, 为整型
    

     2). listen函数
      使服务器的这个端口和IP处于监听状态,等待网络中某一客户机的连接请求。如果客户端有连接请求,端口就会接受这个连接。

    s.listen(backlog)
      s为socket.socket()返回的套接字对象
      backlog : 操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了
    

     3). accept函数
      接受远程计算机的连接请求,建立起与客户机之间的通信连接。服务器处于监听状态时,如果某时刻获得客户机的连接请求,此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统空闲时再处理客户机的连接请求。

    s.accept()
        s为socket.socket()返回的套接字对象
        返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址
    
    • 客户端函数
      1). connect函数
    s.connect(address)
        s为socket.socket()返回的套接字对象
        address : 格式为元组(hostname,port),如果连接出错,返回socket.error错误
    
    • 通用函数
      1). recv函数
    #接收远端主机传来的数据
    s.recv(bufsize[,flag])
        s为socket.socket()返回的套接字对象
        bufsize : 指定要接收的数据大小
        flag : 提供有关消息的其他信息,通常可以忽略
        返回值为数据以字符串形式
    

     2). send函数

    #发送数据给指定的远端主机
    s.send(string[,flag])
        s为socket.socket()返回的套接字对象
        string : 要发送的字符串数据
        flag : 提供有关消息的其他信息,通常可以忽略
        返回值是要发送的字节数量,该数量可能小于string的字节大小。
    s.sendall(string[,flag])
        #完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。
        返回值 : 成功返回None,失败则抛出异常。
    

     3). close函数

    #关闭套接字
    s.close()
      s为socket.socket()返回的套接字对象
    
    • 带异常处理的客户端服务端TCP连接
        在进行网络编程时, 最好使用大量的错误处理, 能够尽量的发现错误, 也能够使代码显得更加严谨。
      1). 服务器端代码
    import socket
    
    phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
    phone.bind(('127.0.0.1',8080)) #插电话卡
    
    phone.listen(5) #开机,backlog
    
    print('starting....')
    while True:
        conn,addr = phone.accept() #接电话
        print('接到来自%s的电话' %addr[0])
        while True:
            client_msg=conn.recv(1024) #收消息
            if len(client_msg) == 0:break  #如果不加,那么正在链接的客户端突然断开,recv便不再阻塞,死循环发生
            print('client msg: %s' %client_msg)
            conn.send(client_msg.upper()) #发消息
        conn.close()
    phone.close()
    

     2). 客户端代码

    
    import socket
    ip_port = ('127.0.0.1',8081)    #电话卡
    BUFSIZE=1024
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #买手机
    s.bind(ip_port) #手机插卡
    s.listen(5) #手机待机
    
    while True:                  #新增接收链接循环,可以不停的接电话
        conn,addr=s.accept()    #手机接电话
        print('接到来自%s的电话' %addr[0])
        while True:                 ##新增通信循环,可以不断的通信,收发消息
            msg=conn.recv(BUFSIZE)  #听消息,听话
            if len(msg) == 0:break  #如果不加,那么正在链接的客户端突然断开,recv便不再阻塞,死循环发生
            print(msg,type(msg))
            conn.send(msg.upper())  #发消息,说话
        conn.close()                #挂电话
    s.close()               #手机关机
    
    3. TCP UDP通信

    UDP通信流程图如下:
    服务端:socket---bind---recvfrom---sendto---close
    客户端:socket------------sendto---recvfrom---close


    UDP通信
    • 创建
    socket.socket([family[, type[, proto]]])
        family : AF_INET (默认ipv4), AF_INET6(ipv6) or AF_UNIX(Unix系统进程间通信)
        type : SOCK_STREAM (TCP), SOCK_DGRAM(UDP) .
        protocol : 一般为0或者默认
    

    如果socket创建失败会抛出一个socket.error异常</code>

    • 常用方法
      1). sendto函数
    #发送UDP数据, 将数据发送到套接字
    s.sendto(string[,flag],address)
    s为socket.socket()返回的套接字对象
    address : 指定远程地址, 形式为(ipaddr,port)的元组
    flag : 提供有关消息的其他信息,通常可以忽略
    返回值 : 发送的字节数。
    

     2). recvfrom函数

    #接受UDP套接字的数据, 与recv()类似
    s.recvfrom(bufsize[.flag])
    返回值 : (data,address)元组, 其中data是包含接收数据的字符串,address是发送数据的套接字地址
    bufsize : 指定要接收的数据大小
    flag : 提供有关消息的其他信息,通常可以忽略
    

     3). close函数

    #关闭套接字
    s.close()
      s为socket.socket()返回的套接字对象
    
    • 简单的客户端服务器UDP连接
      1). 服务器端代码
    import socket
    ip_port=('127.0.0.1',8081)
    udp_server_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #买手机
    udp_server_sock.bind(ip_port)
    
    while True:
        qq_msg,addr=udp_server_sock.recvfrom(1024)
        print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],qq_msg.decode('utf-8')))
        back_msg=input('回复消息: ').strip()
    
        udp_server_sock.sendto(back_msg.encode('utf-8'),addr)
    

     2). 客户端代码
    客户端1

    import socket
    BUFSIZE=1024
    udp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    
    qq_name_dic={
        'TOM':('127.0.0.1',8081),
        'JACK':('127.0.0.1',8081),
        '一棵树':('127.0.0.1',8081),
        '武大郎':('127.0.0.1',8081),
    }
    
    
    while True:
        qq_name=input('请选择聊天对象: ').strip()
        while True:
            msg=input('请输入消息,回车发送: ').strip()
            if msg == 'quit':break
            if not msg or not qq_name or qq_name not in qq_name_dic:continue
            udp_client_socket.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])
    
            back_msg,addr=udp_client_socket.recvfrom(BUFSIZE)
            print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],back_msg.decode('utf-8')))
    
    udp_client_socket.close()
    

    客户端2

    import socket
    BUFSIZE=1024
    udp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    
    qq_name_dic={
        'TOM':('127.0.0.1',8081),
        'JACK':('127.0.0.1',8081),
        '一棵树':('127.0.0.1',8081),
        '武大郎':('127.0.0.1',8081),
    }
    
    
    while True:
        qq_name=input('请选择聊天对象: ').strip()
        while True:
            msg=input('请输入消息,回车发送: ').strip()
            if msg == 'quit':break
            if not msg or not qq_name or qq_name not in qq_name_dic:continue
            udp_client_socket.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])
    
            back_msg,addr=udp_client_socket.recvfrom(BUFSIZE)
            print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],back_msg.decode('utf-8')))
    
    udp_client_socket.close()
    

    常见的套接字对象方法和属性

    名 称 描 述 服务器套接字方法
    s.bind() 将地址(主机名、端口号对)绑定到套接字上
    s.listen() 设置并启动 TCP 监听器
    s.accept() 被动接受 TCP 客户端连接,一直等待直到连接到达(阻塞)
    客户端套接字方法
    s.connect() 主动发起 TCP 服务器连接
    s.connect_ex() connect()的扩展版本,此时会以错误码的形式返回问题,而不是抛出一个异常
    普通的套接字方法
    s.recv() 接收 TCP 消息
    s.recv_into() 接收 TCP 消息到指定的缓冲区
    s.send() 发送 TCP 消息
    s.sendall() 完整地发送 TCP 消息
    s.recvfrom() 接收 UDP 消息
    s.recvfrom_into() 接收 UDP 消息到指定的缓冲区
    s.sendto() 发送 UDP 消息
    s.getpeername() 连接到套接字( TCP)的远程地址
    s.getsockname() 当前套接字的地址
    s.getsockopt() 返回给定套接字选项的值
    s.setsockopt() 设置给定套接字选项的值
    s.shutdown() 关闭连接
    s.close() 关闭套接字
    s.detach() 在未关闭文件描述符的情况下关闭套接字,返回文件描述符
    s.ioctl() 控制套接字的模式(仅支持 Windows)
    面向阻塞的套接字方法
    s.setblocking() 设置套接字的阻塞或非阻塞模式
    s.settimeout() 设置阻塞套接字操作的超时时间
    s.gettimeout() 获取阻塞套接字操作的超时时间
    面向文件的套接字方法
    s.fileno() 套接字的文件描述符
    s.makefile() 创建与套接字关联的文件对象
    数据属性
    s.family 套接字家族
    s.type 套接字类型
    s.proto 套接字协议

    相关文章

      网友评论

          本文标题:python关于Socket编程方法

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