FTP 編寫 3 同時為多個客戶端服務(多執行緒)

2021-08-03 08:26:25 字數 4223 閱讀 7593

在上篇文章中寫了乙個能連線的ftp,但是它只能為乙個客戶端進行服務,而我們知道在現實生活中我們見到的大部分網路應用都能同時為多個使用者提供服務,所以接下來我們的目標是使用多執行緒來使服務端能同時為多個客戶端進行服務。

c++ 多執行緒這個不是網路程式設計的內容,所以在這裡不會詳細講解(其實我也不懂啊,剛看的書就來瞎寫試試了),並且在這裡使用的也不會太複雜(應該)。如果各位有對多執行緒有疑惑或者有興趣,如果是計算機專業的並且學過作業系統的可以去看這本關於 c++ 多執行緒的書:《c++ concurrency in action》,這本書從淺入深地進行講解,很詳細,有了作業系統關於執行緒的知識就容易看懂,上手也比較容易,我就是看了這本書才有膽子試試水的。我也不知道如果沒有看過作業系統看這個容易不,你們也可以去試一試,如果感覺困難的話看一看作業系統的執行緒部分,然後再看。

好了,也就不廢話了,下面開始編寫

首先我們需要把多執行緒部分和 vector 容器的標頭檔案新增進來:

#include 

#include

新增相應的變數,考慮到每有乙個客戶端進行連線我們就需要新開乙個執行緒專門對其進行服務,是動態變化的,所以我們使用指標,並且將執行緒在後台進行執行,這樣我們就不用再對其進行管理,它自個按照**執行就行了。而考慮到指標的記憶體釋放問題,我們使用 vector 容器將每個新建的執行緒指標進行儲存,在程式結束的時候釋放到其占用的記憶體,相應的**如下:

//定義多執行緒指標,用於建立執行緒

std::thread* t;

//用於執行緒的管理,儲存建立的多執行緒指標,程式結束時釋放占用的記憶體

std::vector

tmanage;

//建立新的執行緒,並加入容器中,並將執行緒後台執行

t = new

std::thread(server, saccept);//server是執行緒執行函式,saccept是已經與客戶端連線的套接字

tmanage.push_back(t);

t->detach();

//多執行緒函式,建立的多執行緒執行此函式

void server(socket s) ;

inet_ntop(af_inet, (void*)&cli.sin_addr, clibuf, 16);

std::cout

<< "accept client ip:"

<< clibuf << ":"

<< ntohs(cli.sin_port) << std::endl;

//傳送資訊給客戶端

isend = send(socket, buf, sizeof(buf), 0);

if (isend == socket_error)

else

if (isend == 0)

else

//使用迴圈不斷接受客戶端傳送來的資訊並顯示

while (true)

else

if (irecv == socket_error)

else

}}

//對服務端傳送指令或者資料

int index = 0;//此數不斷遞增,然後傳送給服務端,用於驗證多執行緒是否有用

while (true)

else

if (isend == 0)

else

}

服務端:
#include 

#include

#include

#include

#include

#pragma comment(lib,"ws2_32.lib")

//多執行緒函式,建立的多執行緒執行此函式

void server(socket s);

void main()

//建立socket

slisten = socket(af_inet, sock_stream, 0);

if (slisten == invalid_socket)

//繫結ip位址

ser.sin_family = af_inet;

ser.sin_port = htons(iport);

ser.sin_addr.s_addr = htonl(inaddr_any);

if (bind(slisten, (lpsockaddr)&ser, sizeof(ser)) == socket_error)

//監聽

if (listen(slisten, 5) == socket_error)

ilen = sizeof(cli);//獲取客戶端網路位址的長度

//接受連線和傳送歡迎資訊

//用迴圈使程式一直執行

while (true)

//建立新的執行緒,並加入容器中,並將執行緒後台執行

t = new

std::thread(server, saccept);

tmanage.push_back(t);

t->detach();

}//釋放指標占用的記憶體

for (int i = 0; i < tmanage.size(); i++)

//關閉監聽

closesocket(slisten);

//關閉 winsock

wsacleanup();

}//多執行緒函式,建立的多執行緒執行此函式

void server(socket s) ;

inet_ntop(af_inet, (void*)&cli.sin_addr, clibuf, 16);

std::cout

<< "accept client ip:"

<< clibuf << ":"

<< ntohs(cli.sin_port) << std::endl;

//傳送資訊給客戶端

isend = send(socket, buf, sizeof(buf), 0);

if (isend == socket_error)

else

if (isend == 0)

else

//使用迴圈不斷接受客戶端傳送來的資訊並顯示

while (true)

else

if (irecv == socket_error)

else

}}

客戶端
#include 

#include

#include

#pragma comment(lib,"ws2_32.lib")

void main()

//char addr[20] = ;

//std::cin >> addr;//輸入服務端 ip 位址

char addr[20] = "192.168.1.119";

//建立socket

ser.sin_family = af_inet;

ser.sin_port = htons(iport);

inet_pton(af_inet, addr, (void*)&ser.sin_addr.s_addr);

sclient = socket(af_inet, sock_stream, 0);

if (sclient == invalid_socket)

//連線並進行簡單的操作

if (connect(sclient, (struct sockaddr*)&ser, sizeof(ser)) == invalid_socket)

else

else

if (ilen == socket_error)

std::cout

<< "recv() data from server:"

<< buf << std::endl;

}//對服務端傳送指令或者資料

int index = 0;//此數不斷遞增,然後傳送給服務端,用於驗證多執行緒是否有用

while (true)

else

if (isend == 0)

else

}//關閉連線並退出

closesocket(sclient);

//關閉 winsock

wsacleanup();

system("pause");

}

首先啟動服務端,然後啟動多個客戶端,因為啟動的時間不一樣,所以各個客戶端在服務端顯示的數字是相差還是比較大的

Python編寫FTP客戶端

之前寫過一篇ftp服務端的文章,這篇介紹一下客戶端吧。在使用虛擬機器的時候,由於虛擬機器工具沒安裝成功,所以我決定用ftp在主機與虛擬機器之間傳送檔案,在虛擬機器上開啟ftp服務,然後把客戶端放在主機上,當然也可以顛倒過來。服務端請參考 python實現ftp伺服器 import ftplib im...

MySQL無法同時多個客戶端進行連線解決方案

問題 can t connect to local mysql server through socket var run mysqld mysqld.sock 2 原因 1.首先定位了問題,是由於訪問量太大,導致資料庫連線數不夠,問題出現在資料庫上 2.查詢解決方案修改mysql的配置檔案my.c...

Delphi編寫事件模型客戶端 3

工作者執行緒是傳送和接收資料的主要部分。沒有這部分 是無法實現網路通訊的。今天我就來講一下我寫的工作者執行緒是如何實現的。首先是工作者執行緒的建立和銷毀。constructor tworkthread.create parent tioevents begin inherited create fa...