二、簡單的tcp客戶端
介紹
本文是《winsock程式設計入門(1) - 簡單的tcp伺服器》一文的結局,如果你還沒有讀過第1部分的話,我還是建議你首先讀一下。在本文中,我將示範給你如何編寫乙個簡單的tcp客戶端程式。我們要編寫乙個程式,這個程式將連線到乙個http伺服器,並獲得乙個檔案。
乙個簡單的tcp客戶端程式流程
1、使用wsastartup()初始化winsock庫。
2、使用socket()建立乙個ipproto_tcp socket。
3、使用gethostbyname()/gethostbyaddr()獲取主機資訊。
4、使用connect()和我們建立的套接字連線伺服器。
5、使用send()/recv()傳送和接收資料,直到我們的tcp會話結束。
6、使用closesocket()關閉套接字連線。
7、使用wsacleanup()釋放winsock。
初始化winsock
正如其它每個winsock程式一樣,我們需要初始化winsock庫。這也基本上是一種檢查winsock是否在當前系統可用的方法,對於以前的版本,我們當然希望是這樣。
int wsaret=wsastartup(0x101,&wsadata);
if(wsaret)
return;
建立socket
套接字是一種實體,它擔當了客戶端和伺服器之間的端點。當客戶端連線到伺服器之後,就會存在兩個套接字——客戶端一邊的套接字和相應的伺服器一邊的套接字。讓我們來稱它們為clientsock和serversock。當客戶端在clientsock使用send()時,伺服器可以在serversock使用recv()來接收客戶端所傳送的資料,反之亦然。對於我們的目的,我們使用乙個名為socket()的函式來建立套接字。
socket conn;
conn=socket(af_inet,sock_stream,ipproto_tcp);
if(conn==invalid_socket)
return;
獲取主機資訊
顯然,我們在連線到主機(伺服器)之前,要獲取它的資訊。我們可以使用兩個函式——gethostbyname()和gethostbyaddr()。當我們擁有伺服器的dns名稱時,我們可以使用gethostbyname()函式,例如codeproject.com或ftp.myserver.org之類的名稱。當我們擁有要連線的伺服器的ip位址時,可以使用gethostbyaddr()函式,例如192.168.1.1或202.54.1.100。
顯然,我們希望能使我們的終端使用者既能使用dns名稱,也能使用ip位址。那麼,為了這些工作對他來說透明,我們需要像下面這樣玩乙個小把戲。我們對入口字串使用inet_addr(),這個函式會把乙個ip位址轉換成乙個標準的網路位址格式。這樣一來,如果它返回失敗,我們就可以知道這個字串不是乙個ip位址,如果它成功的話,我們就可以假設它是乙個有效的ip位址了。
if(inet_addr(servername)==inaddr_none)
else
if(hp==null)
連線到伺服器
connect()函式用於向目標伺服器建立連線。我們向它傳遞我們先前建立的套接字和乙個sockaddr結構。我們使用由gethostbyname()/gethostbyaddr()返回的主機位址為sockaddr成員賦值,並輸入乙個要連線的有效埠。
server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
server.sin_family=af_inet;
server.sin_port=htons(80);
if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
會話
當套接字連線建立後,客戶端和伺服器就可以通過send()和recv()來傳送/接收資料了。這通常稱為tcp會話。對於我們的特定情況,我們需要進行http會話。和那些複雜的smtp或pop3協議相比,它還是比較簡單的。http的get命令用於從http伺服器上獲取檔案。這個檔案可以是html檔案、影象檔案、壓縮檔案、***檔案等等。這樣,這個檔案就會被傳送了(這是它最簡單的形式)。當然,還有一些更複雜的方法來使用這個命令。
在我們的程式中,我們像這樣來傳送get命令:
sprintf(buff,"get %s\r\n\r\n",filepath);
send(conn,buff,strlen(buff),0);
while(y=recv(conn,buff,512,0))
關閉連線
現在我們的會話結束了,我們必須關閉連線。在我們的情況下,http連線在檔案傳送完畢之後就會被伺服器關閉了,但是這不要緊,我們仍然需要關閉我們的套接字並釋放資源。在更加複雜的會話中,我們通常在呼叫closesocket()之前呼叫shutdown()來確定緩衝區已經被重新整理,否則可能會有部分資料丟失。
closesocket(conn);
釋放winsock
我們呼叫wsacleanup()來結束winsock的使用。
wsacleanup();
Winsock程式設計入門 2
二 簡單的tcp客戶端 介紹 本文是 winsock程式設計入門 1 簡單的tcp伺服器 一文的結局,如果你還沒有讀過第1部分的話,我還是建議你首先讀一下。在本文中,我將示範給你如何編寫乙個簡單的tcp客戶端程式。我們要編寫乙個程式,這個程式將連線到乙個http伺服器,並獲得乙個檔案。乙個簡單的tc...
Winsock程式設計入門 1
一 簡單的tcp伺服器 介紹 winsock api是一套供microsoft windows作業系統使用的套接字程式庫,它最初基於berkeley套接字,但是其中加入了一些microsoft的特殊改動。在這篇文章中,我要試著給你介紹如何使用winsock來進行套接字程式設計,並假設你沒有在任何作業...
Winsock程式設計入門 2 定址協議 IPv4
winsock是與協議無關的介面,這裡我們主要介紹廣泛使用的ip協議,其版本為當前的ipv4 ipv6暫不介紹 ipv4定址 ipv4中,計算機的位址用32位的二進位制表示,稱為ip位址.當客戶機使用tcp或udp與伺服器通訊時,必須指定其ip位址及通訊埠.伺服器想要偵聽客戶機請求時,也要指定ip位...