好久不來寫BLOG了,最近在寫一個檔案傳送的程式,可是在發檔案中使用fread去讀取檔案,如果定義的緩衝不合適當時的網速就會出問題,設定過小,每次傳送的檔案就非常小,設定過大,在另一端寫檔案就可能沒有完整的寫完上步的內容,緊接著下一步內容就傳過來。當然我們都不希望出現這樣的結果。於是就寫了一個測試網速的程式。
其實大體步驟就是一下:
WINSOCK C/S的建立過程:
伺服器 用戶端
________________________________________________
1 初始化WSA 1 初始化WSA
____________________________________________________
2 建立一個SOCKET 2 建立一個SOCKET
_____________________________________________________
3 綁定SOCKET 3 串連到伺服器
_____________________________________________________
4 在指定的連接埠監聽 4 發送和接受資料
_____________________________________________________
5 接受一個串連 5 中斷連線
______________________________________________________-
6 發送和接受資料
___________________________________________________
7 中斷連線
__________________________________________________
我是一個新手,當然存在很多不曉得的知識,也遇到了不少問題,下面我就我遇到的問題概括一下:
1,初始化WSA。以前從未接觸過SOCKET傳檔案,一看見初始化,不就是要定義嗎?所以就在網上找了半天,什麼也沒找到,後來經我哥解釋,方才知曉,原來#include “winsock.h”中已經涵蓋了WSA 資訊,無非就是
int nRet;
//初始化
WSADATA wsaData;
nRet = WSAStartup(514, &wsaData);//wsaData用來儲存系統傳回的關於WINSOCK的資料
if (nRet != 0)
{
printf("WSAStartup error!/n");//傳回值不等於0,說明初始化失敗
return 0;
}網上現成的,當然一開始我也找到了,可是開始時就是不知道為什麼要這樣就是初始化。畢竟是新手麼。
2,建立一個SOCKET。
//建立SOCKET結構
SOCKET m_socket;//建立一個m_socket的SOCKET控制代碼
m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //建立TCP協議,傳回值儲存在m_socket中
//以下代碼用於檢查傳回值是否有錯誤
if(m_socket == INVALID_SOCKET)
{
printf("Error at socket():%d/n",GetLastError());
WSACleanup(); //釋放資源
return 1; //如果socket()調用失敗,他將返回INVALID_SOCKET
} //應用程式在完成對請求的SOCKET庫使用後,要調用WSACleanup函數來結束SOCKET庫的綁定,並且釋放資源.
這一步倒還是能大概瞭解一下,也都能看的懂。
3,綁定SOCKET。就是使用bind函數進行操作,這一步就是要綁定我們的IP。當然服務端和用戶端都要使用服務端的IP。我這用了一個自動獲得IP的函數(內網和外網的都能獲得)。在IP這我想說幾句,我們如果使用路由器上網,我們所用的IP就有兩種,一個是針對外網的IP,一個是針對路由器內使用者的IP。我是使用路由器上網的,但是發現目前自己的程式還是不能測試A路由器中的使用者和B路由器中使用者之間的網速。起碼我目前是做不到,還請看到文章的同志們能給詳細的介紹個好方法。
4 ,在指定的連接埠監聽。當綁定完成後,伺服器必須建立一個監聽隊列,以接受用戶端的請求。listen()使伺服器進入監聽狀態,該函數調用成功返回0,否則返回 。一旦伺服器開始監聽,我們就要指定一個控制代碼來表示利用ACCEPT()函數接受的串連,這個控制代碼是用來發送和接受資料的表示。還需建立一個SOCKET控制代碼 。Socket AcceptSocket 然後利用無限迴圈來檢測是否有串連傳入。
5, 接受一個串連。一但有串連請求,ACCEPT()函數就會被調用,並且返回這次串連的控制代碼.。
SOCKET AcceptSocket;
AcceptSocket = SOCKET_ERROR;
while(AcceptSocket==SOCKET_ERROR)
{
AcceptSocket=accept(m_socket,NULL,NULL);
printf("Get connect!/n");
break;
}
SOCKET m_server;
m_server = AcceptSocket;
6,發送和接受資料。在控制台裡用ping測試回應時間是電腦使用的是32位元組,所以我們就定義一個32位元組長度的字串,並申請兩個長度為33的緩衝,並將字串放到其中一個緩衝內,傳送資料中,我們使用的是5次迴圈,在服務端用GetTickCount()獲得當前的CPU轉數,一次迴圈後再調用函數GetTickCount()獲得一次轉數,兩者之差即為一次傳送中CPU轉過的圈數,也就對應了一個傳送32位的時間,最後得到5次迴圈的平均值。用戶端使用的是死迴圈,並且把接收到的資料重新send到服務端,並和服務端的緩衝strcmp(),如果是為0就代表用戶端返回正確,也就是一次迴圈成功,但是網路中有可能斷線,此時我採用的處理方法是:發送成功時recv的傳回值是字串的長度,失敗則是返回-1,於是我就使用DWORD dwerror = WSAGetLastError ()獲得dwerror,如果其值為0x2746,則表示網路出問題,我們就跳出迴圈,重新檢測。用戶端也可以使用同樣的方法進行判斷網路問題,當然用戶端還要使用recv函數的傳回值退出死迴圈,條件就是recv傳回值為0,也就是接受不到任何資料。我們得到了傳送32位位元組的平均時間也就能得到每秒能傳送多少位元組了。
7, 中斷連線。釋放緩衝free,釋放連接埠closesocket。最後 WSACleanup()。
對此函數感興趣的話,請到本人自願下載。