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字节的数据。其余的数据都是在缓冲区里面。因为客户端不知道要接收几次。所以服务器端应该把本次要发送的数据大小先发过来,客户端就知道要接收几次了。

原文地址:https://www.cnblogs.com/qing-chen/p/7445085.html