淺談C++實現的TCP實時檔案傳輸
阿新 • • 發佈:2022-03-19
環境:win11,VS2019
分為服務端和客戶端,實現檔案的傳輸
廢話不多說,直接上程式碼,儘量在程式碼裡多加點註釋叭
//服務端
/*寫在前面:
眾所周知,TCP在進行傳輸的時候需要三次握手,很幸運,這些東西windows都封裝好了,不用我一個初學者再寫(我也不會2333)
於是,需要注意的就只有網路通訊本身了。
怎樣才能定位到對方的計算機和對方的對應通訊程式呢?
IP地址用來定位計算機,每一個程式所對應的有一個1~32768的一個數字稱為埠,用這個數字來定位計算機內部眾多的程式。
下文的註釋把套接字比喻為電話機,可能比較明瞭。
*/
#include<cstdio>
#include<winsock2.h>
#include <cstring>
#include<Windows.h>
#pragma comment(lib,"ws2_32.lib")//連結lib庫,
using namespace std;
int main()
{
//初始化套接字(winsocket)
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);//MAKEWORD,把兩個32位int繫結為一個數,(版本號)
//安裝電話機(建立套接字)PF_INET=Ipv4
SOCKET hServSock = socket(PF_INET, SOCK_STREAM, 0 );//IPv4協議,流式套接字,0表示TCP
//繫結電話號碼和分機號(ip&埠)
SOCKADDR_IN servAddr;//定義一個套接字(結構體)
memset(&servAddr, 0, sizeof(servAddr));//清空結構體servAddr內的東西
servAddr.sin_family = AF_INET;//服務端,所以需要的是地址簇(family),AF_INET表示IPv4協議
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);//使用自身的IP地址。htonl:將主機的無符號長整形數轉換成網路位元組順序;INADDR_ANY表示本機IP
servAddr.sin_port = htons(7777);//0~1024不能用;確定埠號;htons轉化型別
bind(hServSock, (SOCKADDR*)&servAddr, sizeof(servAddr));//把電話機和電話號碼繫結,即套接字和儲存地址和埠號的結構體繫結。
//監聽,拿起電話聽筒聽對面是否說話
listen(hServSock, 5);//最多5臺電話
//發現監聽物件,接電話
//獲得對方的ip,埠號
SOCKADDR_IN clntAddr;
int clntAdrSz = sizeof(clntAddr);
SOCKET hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &clntAdrSz);//建立
//說話
//看一下對方的ip地址
//printf("%s", inet_ntoa(clntAddr.sin_addr));
char buf[1025]={0};
recv(hClntSock,buf,1024,0);//先接受檔名
//printf("%s\n", buf);
FILE* fp = fopen(buf, "wb");//用檔名創造二進位制檔案
int bytes;
while ((bytes = recv(hClntSock, buf, 1024, 0)) > 0)//每次接受1024個位元組存在buf裡
{
fwrite(buf, 1, bytes,fp);//把buf裡的東西存在檔案中
}
fclose(fp);//完成,關閉檔案
closesocket(hClntSock);//銷燬套接字
closesocket(hServSock);
//空檔案,接收內容
WSACleanup();//回收套接字
return 0;
}
/*寫在前面
有了前面的服務端,會發現,其實客戶端和服務端長得是很像的
話不多說,直接開始
*/
#include<cstdio> #include<winsock2.h> #include<cstring> #pragma comment(lib,"ws2_32.lib")
using namespace std; int main() { //初始化套接字(winsocket) WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); //打電話 SOCKET hClntSOCK = socket(PF_INET,SOCK_STREAM ,0);//建立流式套接字TCP //127.0.0.1(本機)7777(埠號) SOCKADDR_IN clntAddr; memset(&clntAddr,0,sizeof(clntAddr));//同服務端,清空結構體 clntAddr.sin_family=AF_INET; clntAddr.sin_addr.s_addr=inet_addr("127.0.0.1"); clntAddr.sin_port=htons(7777); //連線 connect(hClntSOCK,(SOCKADDR*)&clntAddr,sizeof(clntAddr)); //傳送一個檔名 send(hClntSOCK,"1.mp4",1024,0); FILE* fp = fopen("1.mp4", "rb");//開啟檔案,只讀 char buf[1024] = { 0 }; int bytes; while ((bytes = fread(buf, 1, 1024, fp) )> 0)//讀取檔案內容,每次一個1024位元組 { send(hClntSOCK, buf, 1024, 0);//把buf裡存的東西send給服務端 } fclose(fp);//傳輸完成,關閉檔案 closesocket(hClntSOCK); WSACleanup();//回收套接字 return 0; }
(To be continued)