自己動手寫下載器:[1]客戶端與服務端socket?

下載工具是最常見的網絡應用之一,比如迅雷、快車、qq旋風。包括各個瀏覽器自身也會有自帶下載功能。為什麼下載工具能夠下載網絡上的東西

,下載工具和瀏覽器有什麼區別?實際上他們都是基於特定協議的網絡應用,只不過各自支持的不盡相同。比如我們瀏覽網頁輸入www.baidu.com,瀏覽器就會顯示出百度的首頁,我們在下載工具中輸入相同的網址,實際上會下載到一個網頁,而這個網頁就是百度首頁。看到這很多人都明白原理了,實際上下載工具所作的事情就是將網絡上的東西存到自己計算機中,而瀏覽器則是把能顯示的頁面直接顯示出來,遇到不能顯示的,它也會提示保存在本地。

當然上面所說的是以開頭的地址,而實際上網絡上我們能遇上的下載地址可不止這些,http、ftp、thunder、ed2k、torrent種子文件;這些都分別對應著各自不同的協議,相對而言http、ftp是最簡單常見的的協議,我們就從這兩個入手研究下載軟件.

在此之前,我們首先要了解的,是網絡中用戶是怎麼連接到服務器並請求數據的,即客戶端和服務端的通信。

所有的網絡應用程序都是從socket編程開始的。下載器同樣就由最簡單的socket編程開始。

以下所有的程序都由C語言實現。

首先我們創建一個服務端,

#include

#include

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

void main()

{

WSADATAwsd;

SOCKETserver;//服務器socket

SOCKADDR_INaddrSrv;

charsendBuf[100];

charrecvBuf[100];

SOCKADDR_INaddrClient;

SOCKETclient;//連接的客戶端socket

intlen;

if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

{

printf("startup failed!
");

return;

}

server=socket(AF_INET,SOCK_STREAM,0);//創建socket

addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//設置地址

addrSrv.sin_family=AF_INET;

addrSrv.sin_port=htons(6000);//設置端口號

bind(server,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//綁定

listen(server,5);//設置最多連接數

len=sizeof(SOCKADDR);

while(1)

{

client=accept(server,(SOCKADDR*)&addrClient,&len);//接收客戶端連接

sprintf(sendBuf,"Welcome%s ",

inet_ntoa(addrClient.sin_addr));

send(client,sendBuf,strlen(sendBuf)+1,0);//發送信息客戶端

recv(client,recvBuf,100,0);//接收客戶端數據

printf("%s
",recvBuf);

closesocket(client);

}

closesocket(client);//關閉連接

WSACleanup();

}

然後編寫一個客戶端,

#include

#include

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

void main()

{

WSADATAwsd;

SOCKETsockClient;//客戶端socket

SOCKADDR_INaddrSrv;

charrecvBuf[100];

if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

{

printf("startup failed!
");

return;

}

sockClient=socket(AF_INET,SOCK_STREAM,0);//創建socket

addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

addrSrv.sin_family=AF_INET;

addrSrv.sin_port=htons(6000);

connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//連接服務器端

recv(sockClient,recvBuf,100,0);//接收服務器端數據

printf("%s
",recvBuf);

send(sockClient,"helloworld",strlen("hello world")+1,0);//向服務器端發送數據

closesocket(sockClient);//關閉連接

WSACleanup();

}

這兩個簡單的服務端和客戶端實現了一個簡單交互,服務端啟動監聽,客戶端連接時,服務端發送給客戶端 welcome的字符串,客戶端則向服務端發送hello world。

如圖

上面實現的只是服務端與客戶端的簡單通信,下面我們通過這樣的數據傳輸來實現從客戶端向服務端請求下載文件,服務端傳送文件給客戶端;

客戶端在連接成功服務端後,發送請求下載的文件名給服務端:

send(sockClient,argv[1],strlen(argv[1])+1,0); //向服務器端發送數據 (argv[1]為請求的資源名) if((fp=fopen(filename,"wb"))==NULL) //創建一個文件 { return ; } while((ret=recv(sockClient,recvBuf,100,0))>0)//接受從服務器發來的數據 { fwrite(recvBuf,1,ret,fp); //保存數據到創建的文件中 }

服務端接收到客戶端請求之後,增加以下處理

if((fp=fopen(recvBuf,"rb"))==NULL)closesocket(client); //請求的文件不存在,則關閉連接 n=fread(sendBuf,1,100,fp); //打開文件並讀取 while(n>0){ send(client,sendBuf,n,0); //發送文件客戶端 n=fread(sendBuf,1,100,fp); }

這樣,服務端的文件就通過socket傳送到了客戶端所在目錄。

自己動手寫下載器 (共1篇)

客戶端, 服務端,
相關問題答案