zoukankan      html  css  js  c++  java
  • python socket实现多个连接

     socket实现多个连接

    前戏很重要~~

    在实现多个连接之前,先实现下多次发送和接收数据。

    如果要多次接收数据,那么在服务器端的接收和客户端的发送部分就必须使用循环。

    以下代码在python3.5下运行。

    服务器端:

    #服务器端
    
    import socket
    server = socket.socket()
    server.bind(('localhost',6969))#绑定要监听的端口
    server.listen() #监听
     
    conn,address = server.accept() #等待接收数据 返回两个值,一个是对方的标记位,一个是对方的地址
    
    while True:
        data = conn.recv(1024) #接收数据,谁发数据给我就用谁的标记位接收
        print(data)
        conn.send(data.upper()) #发送数据,要发给谁就用谁的标记位
    
    server.close()
    

     客户端:

    #客户端
    import socket
    
    client = socket.socket()#声明socket类型,同时生成socket连接对象
    
    client.connect(('localhost',6969))
    while True:
        msg = input('>>').strip()
        client.send(msg.encode("utf-8"))  #发送数据
        data = client.recv(1024)  #接收指定大小的字节
        print(data.decode()) #
    client.close()
    

     直接把用户输入的内容发送给服务器。

    执行结果:

    #=========客户端========
    >>你好
    你好
    >>中国
    中国
    >>hello world
    HELLO WORLD
    >>
    Process finished with exit code 1
    
    #========服务器端=========
    b'xe4xbdxa0xe5xa5xbd'
    b'xe4xb8xadxe5x9bxbd'
    b'hello world'
    Traceback (most recent call last):
    ...
    ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
    
    Process finished with exit code 1
    

     可以看到这里已经实现了多少发送和接收的效果,但是如果客户端断开连接,服务器端也被迫中断。

    在python2下如果客户端突然中断,服务器端并不会直接中断。

    以下实验在Python2环境下。

    单个客户端通信

     服务器端代码:

    #-*-coding:utf-8 -*-
    
    
    import socket
    server = socket.socket()
    server.bind(('localhost',6969))#绑定要监听的端口
    server.listen(1) #监听  最多可以挂起多少个连接
    
    conn,address = server.accept() #等待接收数据 返回两个值,一个是对方的标记位,一个是对方的地址
    
    while True:
        data = conn.recv(1024) #接收数据,谁发数据给我就用谁的标记位接收
        print('recv:',data)
        conn.send(data.upper()) #发送数据,要发给谁就用谁的标记位
    
    server.close()
    

     客户端代码:

    #-*- coding=utf-8 -*-
    #客户端
    import socket
    
    client = socket.socket()#声明socket类型,同时生成socket连接对象
    
    client.connect(('localhost',6969))
    while True:
        msg = raw_input('>>').strip()
    
        client.send(msg.encode("utf-8"))  #发送数据
    
        data = client.recv(1024)  #接收指定大小的字节
        print('recv:',data.decode()) #
    client.close()
    

     开始通信:

    首先客户端先发送数据:

    在看服务器端接收:

    发送接收正常。

    现在用CTRL+c断开客户端之后服务器端的情况。

    修改服务器端代码, 加一个统计,查看下什么时候开始死循环的。

    import socket
    server = socket.socket()
    server.bind(('localhost',6969))#绑定要监听的端口
    server.listen(1) #监听
    
    conn,address = server.accept() #等待接收数据 返回两个值,一个是对方的标记位,一个是对方的地址
    count=0 #统计 条件
    while True:
        data = conn.recv(1024) #接收数据,谁发数据给我就用谁的标记位接收
        print('recv:',data)
        conn.send(data.upper()) #发送数据,要发给谁就用谁的标记位
        count+=1
        if count >10:
            break
    server.close()
    

    客户端发送接收数据结果。

    服务器端发送接收数据结果。

    因为客户端断开,服务器端接收的都是空。

    优化服务器端,断开就退出

    #-*-coding:utf-8 -*-
    
    
    import socket
    server = socket.socket()
    server.bind(('localhost',6969))#绑定要监听的端口
    server.listen(1) #监听
    
    conn,address = server.accept() #等待接收数据 返回两个值,一个是对方的标记位,一个是对方的地址
    
    while True:
        data = conn.recv(1024) #接收数据,谁发数据给我就用谁的标记位接收
    
        print('recv:',data)
        if not data:
            print('客户端断开连接...')  #客户端断开就退出
            break
        conn.send(data.upper()) #发送数据,要发给谁就用谁的标记位
    
    server.close()
    

     客户端:

    服务器端:

    客户端断开,服务器直接退出。

    多个客户端通信

    怎么让服务器端一直保持接收状态呢?

    想要 一直保持接收状态就要在客户端断开之后,继续执行server.accept()。

    对的。在server.accept()之前在加一个while,当一个客户端断开了之后break,跳出最里层的循环的时候,又继续server.accept()。

    #-*-coding:utf-8 -*-
    import socket
    server = socket.socket()
    server.bind(('localhost',6969))#绑定要监听的端口
    server.listen(1) #监听
    while True:
        conn,address = server.accept() #等待接收数据 返回两个值,一个是对方的标记位,一个是对方的地址
    
        while True:
            data = conn.recv(1024) #接收数据,谁发数据给我就用谁的标记位接收
            print('recv:',data)
            if not data:
                print('客户端断开连接...')
                break
            conn.send(data.upper()) #发送数据,要发给谁就用谁的标记位
    
    server.close()
    

     修改并启动服务器端代码。

    客户端1

    客户端2

    服务器端

    断开客户端1之后:

    服务器端

    客户端2

    简单的实现了能多个连接,但是只能同时跟一个客户端通信的功能。。

    模拟SSH

     既然可以发数据过来,那么也可以把这个数据做为命令执行。

    首先修改服务器端,发送过来的命令执行并把结果返回给客户端。

    服务器端代码:

    #-*-coding:utf-8 -*-
    import socket
    import os
    server = socket.socket()
    server.bind(('localhost',6969))#绑定要监听的端口
    server.listen(1) #监听
    while True:
        conn,address = server.accept() #等待接收数据 返回两个值,一个是对方的标记位,一个是对方的地址
    
        while True:
            data = conn.recv(1024) #接收数据,谁发数据给我就用谁的标记位接收
            print('recv:',data)
            if not data:
                print('客户端断开连接...')
                break
            res = os.popen(data).read()
            conn.send(res) #发送数据,要发给谁就用谁的标记位
    
    server.close()
    

     客户端代码:

    #-*- coding=utf-8 -*-
    #客户端
    import socket
    
    client = socket.socket()#声明socket类型,同时生成socket连接对象
    
    client.connect(('localhost',6969))
    while True:
        msg = raw_input('>>').strip()
    
        client.send(msg.encode("utf-8"))  #发送数据
    
        data = client.recv(1024)  #接收指定大小的字节
        print(data) #
    client.close()
    

     执行客户端

    服务器端

    这里是有返回的,如果一条命令的返回数据大于了定义的接收的大小,那么这次客户端接收的数据就不全,剩余的数据要等到服务器下次发送才能接收过来。比如定义的接收数据大小是1024,那么一次只能接收1024字节的数据。其余的数据都是在缓冲区里面。因为客户端不知道要接收几次。所以服务器端应该把本次要发送的数据大小先发过来,客户端就知道要接收几次了。

  • 相关阅读:
    Python导学基础(三)输入、格式化输出、基本运算符
    题解-FJOI2014 树的重心
    题解-CF1307G Cow and Exercise
    题解-SHOI2005 树的双中心
    笔记-CF643E Bear and Destroying Subtrees
    题解-CF643G Choosing Ads
    扩展Lucas
    线性筛筛积性函数
    整除分块(数论)
    2019暑假集训DAY17(problem2.b)(杜教筛)
  • 原文地址:https://www.cnblogs.com/qing-chen/p/7445085.html
Copyright © 2011-2022 走看看