1.工具开发socket编程技术

socker编程技术

socket--一对一

  • TCP协议与UDP协议
    • TCP(transmission control protocol)可靠的,面向连接的协议(eg:打电话)、传输效率低,全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:web浏览器、电子邮件、文件传输等
    • UDP(user datagram protocol)不可靠的,无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统(DNS);视频流;IP语音(volp)--反正数据给你了,不管你拿不拿到

图 2

  • websocket基于应用层协议---HTTP

  • socket基于传输层协议---TCP

  • socket工作原理

图 1

  • 1、服务器根据地址类型、socket类型、协议创建socket

  • 2、服务器为socket绑定ip地址和端口号

  • 3、服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有打开

  • 4、客户端创建socket

  • 5、客户端打开socket,根据服务器IP地址和端口号试图连接服务器socket

  • 6、服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,知道客户端返回连接信息。这时候socket进入阻塞状态,所谓阻塞即accept()方法一直等到客户端返回连接信息后返回,开始接收下一个客户端的连接请求

  • 7、客户端连接成功,向服务器发送连接状态的信息

  • 8、服务器accept方法返回,连接成功

  • 9、客户端向socket写入信息(或服务端向socket写入信息)

  • 10、服务器读取信息(客户端读取信息)

  • 11、客户端关闭

  • 12、服务端关闭

  • socket的常用方法

  • 低级别的网络服务支持基本的socket,它提供了标准的SBD socket API,可以访问底层操作系统socket接口的全部方法

  • 高级别的网络服务模块socketserver,他提供了服务器中心类,可以简化网络服务器的开发

  • 什么是socket编程

    • socket又称套接字,应用程序通常通过套接字向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯
      socket函数
      python中,我们用socket()函数来创建套接字,语法格式如下
    socket.socket([family[,type[,proto]]])
    
    参数
      * family:套接字家族可以使用AF_UNI或者AF_INET.
      * type:套接字类型可以根据是面向连接还是非连接分为SOCK_STREAM或SOCK_DGRAM.
      * protocol:一般不填默认为0
    
  • socket服务端

    • 使用socket模块的socket函数来创建一个socket对象,socket对象可以通过调用其他函数来设置一个socket服务
    • 可以通过调用bind(hostname,port)函数来指定服务的port(端口)
    • 调用socket对象的accept方法,该方法等待客户端的连接,并返回connection对象,表示客户端已经连接到服务端
  • socket客户端

    • socket。connect(hostname,port)方法打开一个TCP,连接到主机为hostname,端口为port的服务端
    • 连接后就可以从服务端获取数据,记住,操作完成后需要关闭连接

socket代码

服务端代码:

        import socket
        ip_port=('127.0.0.1',8888)
        #1-创建socket对象
        sk=socket.socket()
        #2-绑定ip port
        sk.bind(ip_port)
        #3-启动监听
        sk.listen()
        print('---服务器上线了---')
        # 4-阻塞等待连接 返回 套接字 和 客户端的IP
        conn,addr =sk.accept()
        print('客户端的地址>>>:',addr)
        #5-接收数据
        client_data =conn.recv(1024).decode('utf-8')
        print('接收到客户端的数据>>>',client_data)
        #6-发送数据
        send_data = input('请输入>>>')
        conn.sendall(send_data.encode('utf-8'))
        print('发送给客户端的数据>>>',send_data)
        #7-关闭socket
        conn.close()

客户端代码

        import socket
        ip_port=('127.0.0.1',8888)
        #1-创建socket对象
        sk=socket.socket()
        #2-建立连接
        sk.connect(ip_port)
        #3-发送数据
        send_data =input('请输入>>>')
        sk.sendall(send_data.encode('utf-8'))
        print('发送给服务端的数据>>>',send_data)
        #4-接收数据
        server_data =sk.recv(1024).decode('utf-8')
        print('接收到服务端的数据>>>',server_data)
        #5-关闭socket
        sk.close()

局限:只能一对一聊天,不能多对多聊天

socketserver--一对多

socketserver代码

服务端:

import socketserver
#1-需要继承一个类BaseRequestHandler 实现handle方法
print('---服务启动完成,等待客户端中---')
class SKserver(socketserver.BaseRequestHandler):
    def handle(self):
        print('---有客户端上线了---')

        #处理逻辑,self.request方法
        while True:
            #接收数据
            client_data =self.request.recv(1024).decode('utf-8')
            print('接收到客户端的数据>>>',client_data)
            #发送数据
            send_data=input('请输入:>>>')
            self.request.sendall(send_data.encode('utf-8'))
            print('发送给客户端的数据>>>',send_data)
        self.request.close()
#2-创建服务,多线程方式ThreadingTCPServer
sk=socketserver.ThreadingTCPServer(('127.0.0.1',8888),SKserver)
#3-保持一直在线
sk.serve_forever()

客户A 客户B复制A的代码

import socket
ip_port=('127.0.0.1',8888)
#1-创建socket对象
sk=socket.socket()
#2-建立连接
sk.connect(ip_port)
while True:
    #3-发送数据
    send_data =input('a:'+'请输入>>>')
    sk.sendall(send_data.encode('utf-8'))
    print('发送给服务端的数据>>>',send_data)
    #4-接收数据
    server_data =sk.recv(1024).decode('utf-8')
    print('接收到服务端的数据>>>',server_data)
#5-关闭socket
sk.close()

运行结果
图 4
客户端A:

    a:请输入>>>a
    发送给服务端的数据>>> a
    接收到服务端的数据>>> aa
    a:请输入>>>aaa
    发送给服务端的数据>>> aaa
    接收到服务端的数据>>> aaaa
    a:请输入>>>

客户端B:

    b:请输入>>>b
    发送给服务端的数据>>> b
    接收到服务端的数据>>> bb
    b:请输入>>>bbb
    发送给服务端的数据>>> bbb
    接收到服务端的数据>>> bbbb
    b:请输入>>>

问题记录

  • 1、TypeError: recv() takes at least 1 argument (0 given)

    client_data =conn.recv()
    TypeError: recv() takes at least 1 argument (0 given)
    
    • 原因分析:
      • 未指定接收数据大小
    • 解决方法
      • 指定数据大小
      • client_data =conn.recv(1024)
  • 2、TypeError: a bytes-like object is required, not 'str'

    sk.sendall(send_data)
    TypeError: a bytes-like object is required, not 'str'
    
    • 原因分析:
      • 未指定编码格式,需要字节流而不是字符串
    • 解决方法
      • 指定编码格式为utf-8
      • sk.sendall(send_data.encode('utf-8'))
  • 3、OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。

      self.socket.bind(self.server_address)
      OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。
    
    • 原因分析:
      • 当我们在PyCharm中把运行窗口中运行状态终结了,实质是执行的python程序还没有结束, 所以打开windows任务管理器,把名为python的进程统统结束。
    • 解决方法
      • 任务管理器,关闭python运行程序
        图 3
原文地址:https://www.cnblogs.com/xiehuangzhijia/p/14969200.html