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'\xe4\xbd\xa0\xe5\xa5\xbd'
b'\xe4\xb8\xad\xe5\x9b\xbd'
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字節的數據。其余的數據都是在緩沖區里面。因為客戶端不知道要接收幾次。所以服務器端應該把本次要發送的數據大小先發過來,客戶端就知道要接收幾次了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM