Windows Socket程式設計之TCP實現大檔案的傳輸
阿新 • • 發佈:2019-01-31
前言:
本文實現以下功能:
在客戶端,使用者選擇本地的某個檔案,併發送到伺服器端。
在伺服器端,接收客戶端傳輸的資料流,並按IP 地址儲存在伺服器端(文
件名重複的,可以覆蓋)。
如果傳輸過程中伺服器端發現客戶端斷開,伺服器端應刪除檔案,並在螢幕
上提示,如“IP:1.2.3.4 發來abcd.txt 檔案過程中失去連線。”。如果客戶端發
現伺服器端不工作,客戶端應有提示“伺服器1.2.3.5:62345 失去連線”。
一、Socket TCP傳輸的流程
二、程式碼實現
1.FileHelper用來進行與檔案相關的操作
#include<stdio.h> #include<stdlib.h> #include <WINSOCK2.H> #include <STDIO.H> #pragma comment(lib,"ws2_32.lib") class FileHelper { private: FILE *f; char path_buffer[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; public: FILE * selectfile() { printf("請輸入要傳送的檔名\n"); scanf("%s",path_buffer); if (f=fopen(path_buffer,"rb")) { printf("檔案開啟成功\n"); return f; } else { printf("檔案不存在,請重新輸入\n"); return selectfile(); } } char * getFileName() { _splitpath(path_buffer, drive, dir, fname, ext); return strcat(fname, ext); } FILE * createFile(char *name) { remove(name); if (f = fopen(name, "ab")) { printf("檔案建立成功\n"); } else { printf("檔案建立失敗\n"); } return f; } bool createDir(char *dir) { char head[MAX_PATH] = "md "; return system(strcat(head, dir)); } };
2.Client端
#include <stdio.h> #include <WINSOCK2.H> #include <STDIO.H> #include"FileHelper.h" #pragma comment(lib,"ws2_32.lib") int main(int argc, char* argv[]) { WORD sockVersion = MAKEWORD(2,2);//版本號 WSADATA data; //用來儲存WSAStartup呼叫後返回的windows Sockets資料 FileHelper fh; if(WSAStartup(sockVersion, &data) != 0) { return 0; } sockaddr_in serAddr; serAddr.sin_family = AF_INET; serAddr.sin_port = htons(8888); serAddr.sin_addr.S_un.S_addr = inet_addr("59.77.13.189"); while (true) { SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sclient == INVALID_SOCKET) { printf("invalid socket !"); return 0; } if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR) { printf("connect error !"); closesocket(sclient); return 0; } FILE *f=fh.selectfile(); char sendData[BUFSIZ]; char recData[BUFSIZ]; char over[BUFSIZ] = "Finnal"; char * name = fh.getFileName(); strcpy(sendData, name); printf("%s\n", sendData); int nCount; long long sum = 0; send(sclient, sendData, strlen(sendData)+1, 0); int ret = recv(sclient, recData, BUFSIZ, 0); printf(recData); while ((nCount=fread(sendData,1,BUFSIZ,f))>0) { printf("%db\n",sum+=nCount); send(sclient, sendData, nCount, 0); int ret = recv(sclient, recData, BUFSIZ, 0); if (ret >0) { //recData[ret] = 0x00; printf(recData); } else { printf("與伺服器失去連線"); break; } } send(sclient, over, BUFSIZ, 0); ret = recv(sclient, recData, BUFSIZ, 0); if (ret>0&&strcmp(recData,over)==0) { printf("傳輸成功!"); } fclose(f); closesocket(sclient); } WSACleanup(); return 0; }
3.Server端
#include <stdio.h> #include <stdio.h> #include <winsock2.h> #include "FileHelper.h" #pragma comment(lib,"ws2_32.lib") int main(int argc, char* argv[]) { //初始化WSA WORD sockVersion = MAKEWORD(2, 2); WSADATA wsaData; FileHelper fh; if (WSAStartup(sockVersion, &wsaData) != 0) { return 0; } //建立套接字 SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (slisten == INVALID_SOCKET) { printf("socket error !"); return 0; } //繫結IP和埠 sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(8888); sin.sin_addr.S_un.S_addr = INADDR_ANY; if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { printf("bind error !"); } //開始監聽 if (listen(slisten, 5) == SOCKET_ERROR) { printf("listen error !"); return 0; } //迴圈接收資料 SOCKET sClient; sockaddr_in remoteAddr; int nAddrlen = sizeof(remoteAddr); char revData[BUFSIZ]; while (true) { printf("等待連線...\n"); sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen); if (sClient == INVALID_SOCKET) { printf("accept error !"); continue; } printf("接受到一個連線:%s \r\n", inet_ntoa(remoteAddr.sin_addr)); /*if (fh.createDir(inet_ntoa(remoteAddr.sin_addr))) printf("資料夾建立成功!");*/ int ret = 0; long long count = 0; char sendData[BUFSIZ] = "你好,TCP客戶端!\n"; ret = recv(sClient, revData, BUFSIZ, 0); char fromname[BUFSIZ] = {}; strcpy(fromname, revData); char mid[3] = "\\"; char finame[MAX_PATH] = {}; char over[BUFSIZ] = "Finnal"; strcat(finame, inet_ntoa(remoteAddr.sin_addr)); printf(finame); strcat(finame, mid); strcat(finame, revData); //printf(finame); FILE *f = fh.createFile(finame); send(sClient, sendData, BUFSIZ, 0); while ((ret = recv(sClient, revData, BUFSIZ, 0)) > 0) { //printf("%d\n", ret); printf("%db\n", count += ret); if (strcmp(revData,over)==0) { printf("檔案%s傳輸成功\n", fromname); break; send(sClient, over, BUFSIZ, 0); } fwrite(revData, 1, ret, f); send(sClient, sendData, BUFSIZ, 0); } fclose(f); if (strcmp(revData, over) != 0) { printf("IP:%s發來的%s傳輸過程中失去連線\n", inet_ntoa(remoteAddr.sin_addr),fromname); remove(finame); } closesocket(sClient); } closesocket(slisten); WSACleanup(); return 0; }