欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++實(shí)現(xiàn)FTP綜合應(yīng)用詳解

 更新時(shí)間:2022年08月02日 17:22:05   作者:十夢(mèng)九有妳  
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)FTP綜合應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文為大家分享了FTP綜合應(yīng)用編程(C++),供大家參考,具體內(nèi)容如下

1.學(xué)校實(shí)驗(yàn)

借鑒了網(wǎng)上一位大佬的作品,然后自己改改拿來(lái)完成了算是還行的作品。

代碼一共大概是900多行,可以直接粘貼下來(lái)看看,其實(shí)還是很容易理解的。

運(yùn)行的截圖附上:

客戶(hù)端:

服務(wù)器端:

2.服務(wù)器端代碼

頭文件:(sizes.h)

#pragma once
?
//服務(wù)器偵聽(tīng)控制連接請(qǐng)求的端口
#define CMD_PORT 5858
//客戶(hù)機(jī)偵聽(tīng)數(shù)據(jù)連接請(qǐng)求的端口
#define DATA_PORT 5850
//命令報(bào)文參數(shù)緩存的大小
#define CMD_PARAM_SIZE 256
//回復(fù)報(bào)文消息緩存的大小
#define RSPNS_TEXT_SIZE 256
#define BACKLOG 10
#define DATA_BUFSIZE 4096
?
//命令類(lèi)型
typedef enum {
?? ?LS, PWD, CD, DOWN, UP, QUIT
} CmdID;
?
//命令報(bào)文,從客戶(hù)端發(fā)往服務(wù)器
typedef struct _CmdPacket {
?? ?CmdID cmdid;
?? ?char param[CMD_PARAM_SIZE];
} CmdPacket;
?
//回復(fù)報(bào)文的類(lèi)型
typedef enum {
?? ?OK, ERR
} RspnsID;
?
//回復(fù)報(bào)文,從服務(wù)器發(fā)往客戶(hù)端
typedef struct _RspnsPacket {
?? ?RspnsID rspnsid;
?? ?char text[RSPNS_TEXT_SIZE];
} RspnsPacket;

源文件:(服務(wù)器端.cpp)

#include <WinSock2.h>
#include "sizes.h"
#include <iostream>
?
#pragma comment(lib, "ws2_32.lib")
?
//創(chuàng)建線(xiàn)程時(shí)傳遞的數(shù)據(jù)結(jié)構(gòu),內(nèi)含控制連接套接字和客戶(hù)端地址信息:
struct threadData {
?? ?SOCKET tcps;
?? ?sockaddr_in clientaddr;
};
?
//全局函數(shù)聲明:
//FTP初始化,創(chuàng)建一個(gè)偵聽(tīng)套接字:
int InitFTP(SOCKET *pListenSock);
int InitDataSocket(SOCKET *pDatatcps, SOCKADDR_IN *pClientAddr);
int ProcessCmd(SOCKET tcps, CmdPacket* pCmd, SOCKADDR_IN *pClientAddr);
int SendRspns(SOCKET tcps, RspnsPacket* prspns);
int RecvCmd(SOCKET tcps, char* pCmd);
int SendFileList(SOCKET datatcps);
int SendFileRecord(SOCKET datatcps, WIN32_FIND_DATA* pfd);
int SendFile(SOCKET datatcps, FILE* file);
int RecvFile(SOCKET datatcps, char* filename);
int FileExists(const char *filename);
?
//線(xiàn)程函數(shù),參數(shù)包括相應(yīng)控制連接的套接字:
DWORD WINAPI ThreadFunc(LPVOID lpParam) {
?? ?SOCKET tcps;
?? ?sockaddr_in clientaddr;
?? ?tcps = ((struct threadData *)lpParam)->tcps;
?? ?clientaddr = ((struct threadData *)lpParam)->clientaddr;
?? ?printf("socket的編號(hào)是:%u.\n", tcps);
?
?? ?//發(fā)送回復(fù)報(bào)文給客戶(hù)端,內(nèi)含命令使用說(shuō)明:
?? ?printf("Serve client %s:%d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
?? ?RspnsPacket rspns = { OK,
?? ??? ??? ?"歡迎進(jìn)入FTP綜合應(yīng)用系統(tǒng)!\n"
?? ??? ??? ?"你可以使用的命令:\n"
?? ??? ??? ?"ls\t<展示當(dāng)前目錄下的文件(夾),無(wú)需參數(shù)>\n"
?? ??? ??? ?"pwd\t<展示當(dāng)前目錄的絕對(duì)路徑,無(wú)需參數(shù)>\n"
?? ??? ??? ?"cd\t<切換到指定目錄,參數(shù)為路徑>\n"
?? ??? ??? ?"down\t<下載文件,參數(shù)為文件名>\n"
?? ??? ??? ?"up\t<上傳文件,參數(shù)為文件名>\n"
?? ??? ??? ?"quit\t<退出系統(tǒng),無(wú)需參數(shù)>\n"
?? ?};
?? ?SendRspns(tcps, &rspns);
?
?? ?//循環(huán)獲取客戶(hù)端命令報(bào)文并進(jìn)行處理
?? ?for (;;) {
?? ??? ?CmdPacket cmd;
?? ??? ?if (!RecvCmd(tcps, (char *)&cmd))
?? ??? ??? ?break;
?? ??? ?if (!ProcessCmd(tcps, &cmd, &clientaddr))
?? ??? ??? ?break;
?? ?}
?
?? ?//線(xiàn)程結(jié)束前關(guān)閉控制連接套接字:
?? ?closesocket(tcps);
?? ?delete lpParam;
?? ?return 0;
}
?
int main(int argc, char* argv[]) {
?? ?SOCKET tcps_listen; ?//FTP服務(wù)器控制連接偵聽(tīng)套接字
?? ?struct threadData *pThInfo;
?
?? ?if (!InitFTP(&tcps_listen)) ?//FTP初始化
?? ??? ?return 0;
?? ?printf("FTP服務(wù)器開(kāi)始監(jiān)聽(tīng),端口號(hào)為:%d。。。。。。\n", CMD_PORT);
?
?? ?//循環(huán)接受客戶(hù)端連接請(qǐng)求,并生成線(xiàn)程去處理:
?? ?for (;;) {
?? ??? ?pThInfo = NULL;
?? ??? ?pThInfo = new threadData;
?? ??? ?if (pThInfo == NULL) {
?? ??? ??? ?printf("為新線(xiàn)程申請(qǐng)空間失敗。\n");
?? ??? ??? ?continue;
?? ??? ?}
?
?? ??? ?int len = sizeof(struct threadData);
?? ??? ?//等待接受客戶(hù)端控制連接請(qǐng)求
?? ??? ?pThInfo->tcps = accept(tcps_listen, (SOCKADDR*)&pThInfo->clientaddr, &len);
?
?? ??? ?//創(chuàng)建一個(gè)線(xiàn)程來(lái)處理相應(yīng)客戶(hù)端的請(qǐng)求:
?? ??? ?DWORD dwThreadId, dwThrdParam = 1;
?? ??? ?HANDLE hThread;
?
?? ??? ?hThread = CreateThread(
?? ??? ??? ?NULL, ? ? ? ? ? ? ? //無(wú)需安全性的繼承
?? ??? ??? ?0,?? ??? ??? ??? ??? ?//默認(rèn)線(xiàn)程棧大小
?? ??? ??? ?ThreadFunc,?? ??? ??? ?//線(xiàn)程入口函數(shù)
?? ??? ??? ?pThInfo,?? ??? ??? ?//線(xiàn)程入口函數(shù)的參數(shù)
?? ??? ??? ?0,?? ??? ??? ??? ??? ?//立即啟動(dòng)線(xiàn)程
?? ??? ??? ?&dwThreadId);?? ??? ?//返回線(xiàn)程的id值
?
?? ??? ?//檢查返回值是否創(chuàng)建線(xiàn)程成功
?? ??? ?if (hThread == NULL) {
?? ??? ??? ?printf("創(chuàng)建線(xiàn)程失敗。\n");
?? ??? ??? ?closesocket(pThInfo->tcps);
?? ??? ??? ?delete pThInfo;
?? ??? ?}
?? ?}
?
?? ?return 0;
?
}
?
//FTP初始化,創(chuàng)建一個(gè)偵聽(tīng)套接字:
?
int InitFTP(SOCKET *pListenSock) {
?? ?//按照此步驟創(chuàng)建新的服務(wù)器端套接字,嗯,沒(méi)錯(cuò),前三個(gè)都是這個(gè)步驟
?? ?//startup->socket->bind->listen
?? ?WORD wVersionRequested;
?? ?WSADATA wsaData;
?? ?int err;
?? ?SOCKET tcps_listen;
?
?? ?wVersionRequested = MAKEWORD(2, 2);
?? ?err = WSAStartup(wVersionRequested, &wsaData);
?? ?if (err != 0) {
?? ??? ?printf("Winsock初始化時(shí)發(fā)生錯(cuò)誤!\n");
?? ??? ?return 0;
?? ?}
?? ?if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
?? ??? ?WSACleanup();
?? ??? ?printf("無(wú)效Winsock版本!\n");
?? ??? ?return 0;
?? ?}
?
?? ?tcps_listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
?? ?if (tcps_listen == INVALID_SOCKET) {
?? ??? ?WSACleanup();
?? ??? ?printf("創(chuàng)建Socket失敗!\n");
?? ??? ?return 0;
?? ?}
?
?? ?SOCKADDR_IN tcpaddr;
?? ?tcpaddr.sin_family = AF_INET;
?? ?tcpaddr.sin_port = htons(CMD_PORT);
?? ?tcpaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
?? ?err = bind(tcps_listen, (SOCKADDR*)&tcpaddr, sizeof(tcpaddr));
?? ?if (err != 0) {
?? ??? ?err = WSAGetLastError();
?? ??? ?WSACleanup();
?? ??? ?printf("Scoket綁定時(shí)發(fā)生錯(cuò)誤!\n");
?? ??? ?return 0;
?? ?}
?? ?err = listen(tcps_listen, 3);
?? ?if (err != 0) {
?? ??? ?WSACleanup();
?? ??? ?printf("Scoket監(jiān)聽(tīng)時(shí)發(fā)生錯(cuò)誤!\n");
?? ??? ?return 0;
?? ?}
?
?? ?*pListenSock = tcps_listen;
?? ?return 1;
}
?
?
//建立數(shù)據(jù)連接
//pDatatcps:用于存儲(chǔ)數(shù)據(jù)連接套接字
//pClientAddr:指向客戶(hù)端的控制連接套接字地址,需要使用其中的IP地址
//返回值:0表示失敗,1正常
int InitDataSocket(SOCKET *pDatatcps, SOCKADDR_IN *pClientAddr) {
?? ?SOCKET datatcps;
?
?? ?//創(chuàng)建socket
?? ?datatcps = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
?? ?if (datatcps == INVALID_SOCKET) {
?? ??? ?printf("Creating data socket failed!\n");
?? ??? ?return 0;
?? ?}
?
?? ?SOCKADDR_IN tcpaddr;
?? ?memcpy(&tcpaddr, pClientAddr, sizeof(SOCKADDR_IN));
?? ?tcpaddr.sin_port = htons(DATA_PORT); ? ?//如若有什么意外只需要在頭文件修改端口值
?
?? ?//請(qǐng)求連接客戶(hù)端
?? ?if (connect(datatcps, (SOCKADDR*)&tcpaddr, sizeof(tcpaddr)) == SOCKET_ERROR) {
?? ??? ?printf("Connecting to client failed!\n");
?? ??? ?closesocket(datatcps);
?? ??? ?return 0;
?? ?}
?
?? ?*pDatatcps = datatcps;
?? ?return 1;
}
?
//處理命令報(bào)文
//tcps:控制連接套接字
//pcmd:指向待處理的命令報(bào)文
//pClientAddr:指向客戶(hù)端控制連接套接字地址
//返回值:0表示有錯(cuò)或者需要結(jié)束連接,1正常
?
int ProcessCmd(SOCKET tcps, CmdPacket* pCmd, SOCKADDR_IN *pClientAddr) {
?? ?SOCKET datatcps; ? //數(shù)據(jù)連接套接字
?? ?RspnsPacket rspns; ?//回復(fù)報(bào)文
?? ?FILE* file;
?
?? ?//根據(jù)命令類(lèi)型分派執(zhí)行:
?? ?switch (pCmd->cmdid) {
?? ?case LS://展示當(dāng)前目錄下的文件列表
?? ??? ?//首先建立數(shù)據(jù)連接:
?? ??? ?if (!InitDataSocket(&datatcps, pClientAddr))
?? ??? ??? ?return 0;
?? ??? ?//發(fā)送文件列表信息:
?? ??? ?if (!SendFileList(datatcps))
?? ??? ??? ?return 0;
?? ??? ?break;
?? ?case PWD://展示當(dāng)前目錄的絕對(duì)路徑
?? ??? ?rspns.rspnsid = OK;
?? ??? ?//獲取當(dāng)前目錄,并放至回復(fù)報(bào)文中
?? ??? ?if (!GetCurrentDirectory(RSPNS_TEXT_SIZE, rspns.text))
?? ??? ??? ?strcpy(rspns.text, "Can't get current dir!\n");
?? ??? ?if (!SendRspns(tcps, &rspns))
?? ??? ??? ?return 0;
?? ??? ?break;
?? ?case CD://設(shè)置當(dāng)前目錄,使用win32 API 接口函數(shù)
?? ??? ?if (SetCurrentDirectory(pCmd->param)) {
?? ??? ??? ?rspns.rspnsid = OK;
?? ??? ??? ?if (!GetCurrentDirectory(RSPNS_TEXT_SIZE, rspns.text))
?? ??? ??? ??? ?strcpy(rspns.text, "切換當(dāng)前目錄成功!但是不能獲取到當(dāng)前的文件列表!\n");
?? ??? ?}
?? ??? ?else {
?? ??? ??? ?strcpy(rspns.text, "不能更換到所選目錄!\n");
?? ??? ?}
?? ??? ?if (!SendRspns(tcps, &rspns)) ? //發(fā)送回復(fù)報(bào)文
?? ??? ??? ?return 0;
?? ??? ?break;
?? ?case DOWN://處理下載文件請(qǐng)求:
?? ??? ?file = fopen(pCmd->param, "rb"); ? //打開(kāi)要下載的文件
?? ??? ?if (file) {
?? ??? ??? ?rspns.rspnsid = OK;
?? ??? ??? ?sprintf(rspns.text, "下載文件%s\n", pCmd->param);
?? ??? ??? ?if (!SendRspns(tcps, &rspns)) {
?? ??? ??? ??? ?fclose(file);
?? ??? ??? ??? ?return 0;
?? ??? ??? ?}
?? ??? ??? ?else {
?? ??? ??? ??? ?//創(chuàng)建額外的數(shù)據(jù)連接來(lái)傳送數(shù)據(jù):
?? ??? ??? ??? ?if (!InitDataSocket(&datatcps, pClientAddr)) {
?? ??? ??? ??? ??? ?fclose(file);
?? ??? ??? ??? ??? ?return 0;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?if (!SendFile(datatcps, file))
?? ??? ??? ??? ??? ?return 0;
?? ??? ??? ??? ?fclose(file);
?? ??? ??? ?}
?? ??? ?}
?? ??? ?else ?//打開(kāi)文件失敗
?? ??? ?{
?? ??? ??? ?rspns.rspnsid = ERR;
?? ??? ??? ?strcpy(rspns.text, "不能打開(kāi)文件!\n");
?? ??? ??? ?if (!SendRspns(tcps, &rspns))
?? ??? ??? ??? ?return 0;
?? ??? ?}
?? ??? ?break;
?? ?case UP://處理上傳文件請(qǐng)求
?? ??? ?//首先發(fā)送回復(fù)報(bào)文
?? ??? ?char filename[64];
?? ??? ?strcpy(filename, pCmd->param);
?? ??? ?//首先看一下服務(wù)器上是否已經(jīng)有這個(gè)文件里,如果有就告訴客戶(hù)端不用傳輸了
?? ??? ?if (FileExists(filename)) {
?? ??? ??? ?rspns.rspnsid = ERR;
?? ??? ??? ?sprintf(rspns.text, "服務(wù)器已經(jīng)存在名字為%s的文件!\n", filename);
?? ??? ??? ?if (!SendRspns(tcps, &rspns))
?? ??? ??? ??? ?return 0;
?? ??? ?}
?? ??? ?else {
?? ??? ??? ?rspns.rspnsid = OK;
?? ??? ??? ?if (!SendRspns(tcps, &rspns))
?? ??? ??? ??? ?return 0;
?? ??? ??? ?//另建立一個(gè)數(shù)據(jù)連接來(lái)接受數(shù)據(jù):
?? ??? ??? ?if (!InitDataSocket(&datatcps, pClientAddr))
?? ??? ??? ??? ?return 0;
?? ??? ??? ?if (!RecvFile(datatcps, filename))
?? ??? ??? ??? ?return 0;
?? ??? ?}
?? ??? ?break;
?? ?case QUIT:
?? ??? ?printf("客戶(hù)端斷開(kāi)連接。\n");
?? ??? ?rspns.rspnsid = OK;
?? ??? ?strcpy(rspns.text, "常來(lái)??!\n");
?? ??? ?SendRspns(tcps, &rspns);
?? ??? ?return 0;
?
?
?? ?}
?
?? ?return 1;
?
}
?
//發(fā)送回復(fù)報(bào)文
int SendRspns(SOCKET tcps, RspnsPacket* prspns) {
?? ?if (send(tcps, (char *)prspns, sizeof(RspnsPacket), 0) == SOCKET_ERROR) {
?? ??? ?printf("與客戶(hù)端失去連接。\n");
?? ??? ?return 0;
?? ?}
?? ?return 1;
}
?
//接收命令報(bào)文
//tcps:控制連接套接字
//pCmd:用于存儲(chǔ)返回的命令報(bào)文
//返回值:0表示有錯(cuò)或者連接已經(jīng)斷開(kāi),1表示正常
int RecvCmd(SOCKET tcps, char* pCmd) {?? ??? ??? ??? ??? ?//used to receive command from client
?? ?int nRet;
?? ?int left = sizeof(CmdPacket);
?
?? ?//從控制連接中讀取數(shù)據(jù),大小為 sizeof(CmdPacket):
?? ?while (left) {
?? ??? ?nRet = recv(tcps, pCmd, left, 0);
?? ??? ?if (nRet == SOCKET_ERROR) {
?? ??? ??? ?printf("從客戶(hù)端接受命令時(shí)發(fā)生未知錯(cuò)誤!\n");
?? ??? ??? ?return 0;
?? ??? ?}
?? ??? ?if (!nRet) {
?? ??? ??? ?printf("客戶(hù)端關(guān)閉了連接!\n");
?? ??? ??? ?return 0;
?? ??? ?}
?
?? ??? ?left -= nRet;
?? ??? ?pCmd += nRet;
?? ?}
?? ?return 1; ? //成功獲取命令報(bào)文
}
?
?
//發(fā)送一項(xiàng)文件信息:
int SendFileRecord(SOCKET datatcps, WIN32_FIND_DATA* pfd) { ? ? ? ? ? ? ? ? ? ?//used to send response to client
?? ?char filerecord[MAX_PATH + 32];
?? ?FILETIME ft;
?? ?FileTimeToLocalFileTime(&pfd->ftLastWriteTime, &ft);
?? ?SYSTEMTIME lastwtime;
?? ?FileTimeToSystemTime(&ft, &lastwtime);
?? ?char* dir = (char*)(pfd->dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY ? "<DIR>" : "");
?? ?sprintf(filerecord, "%04d-%02d-%02d%02d:%02d ? %5s ? %10d ? %-20s\n",
?? ??? ?lastwtime.wYear,
?? ??? ?lastwtime.wMonth,
?? ??? ?lastwtime.wDay,
?? ??? ?lastwtime.wHour,
?? ??? ?lastwtime.wMinute,
?? ??? ?dir,
?? ??? ?pfd->nFileSizeLow,
?? ??? ?pfd->cFileName);
?? ?if (send(datatcps, filerecord, strlen(filerecord), 0) == SOCKET_ERROR) {
?? ??? ?printf("發(fā)送文件列表時(shí)發(fā)生未知錯(cuò)誤!\n");
?? ??? ?return 0;
?
?? ?}
?? ?return 1;
}
?
?
//發(fā)送文件列表信息
//datatcps:數(shù)據(jù)連接套接字
//返回值:0表示出錯(cuò),1表示正常
int SendFileList(SOCKET datatcps) {
?? ?HANDLE hff;
?? ?WIN32_FIND_DATA fd;
?
?? ?//搜索文件
?? ?hff = FindFirstFile("*", &fd);
?? ?if (hff == INVALID_HANDLE_VALUE) ?//發(fā)生錯(cuò)誤
?? ?{
?? ??? ?const char* errstr = "不能列出文件!\n";
?? ??? ?printf("文件列表輸出失??!\n");
?? ??? ?if (send(datatcps, errstr, strlen(errstr), 0) == SOCKET_ERROR) {
?? ??? ??? ?printf("發(fā)送給文件列表時(shí)發(fā)生未知錯(cuò)誤!\n");
?? ??? ?}
?? ??? ?closesocket(datatcps);?? ??? ??? ?return 0;
?? ?}
?
?? ?BOOL fMoreFiles = TRUE;
?? ?while (fMoreFiles) {
?? ??? ?//發(fā)送此項(xiàng)文件信息:
?? ??? ?if (!SendFileRecord(datatcps, &fd)) {
?? ??? ??? ?closesocket(datatcps);
?? ??? ??? ?return 0;
?? ??? ?}
?? ??? ?//搜索下一個(gè)文件
?? ??? ?fMoreFiles = FindNextFile(hff, &fd);
?? ?}
?? ?closesocket(datatcps);
?? ?return 1;
}
?
//通過(guò)數(shù)據(jù)連接發(fā)送文件
int SendFile(SOCKET datatcps, FILE* file) {
?? ?char buf[1024];
?? ?printf("發(fā)送文件數(shù)據(jù)中。。。。。。");
?? ?for (;;) {?? ??? ??? ??? ?//從文件中循環(huán)讀取數(shù)據(jù)并發(fā)送客戶(hù)端
?? ??? ?int r = fread(buf, 1, 1024, file);
?? ??? ?if (send(datatcps, buf, r, 0) == SOCKET_ERROR) {
?? ??? ??? ?printf("與客戶(hù)端失去連接!\n");
?? ??? ??? ?closesocket(datatcps);
?? ??? ??? ?return 0;
?? ??? ?}
?? ??? ?if (r < 1024) ? //文件傳輸結(jié)束
?? ??? ?{
?? ??? ??? ?break;
?? ??? ?}
?? ?}
?? ?closesocket(datatcps);
?? ?printf("完成傳輸!\n");
?? ?return 1;
}
?
//接收文件
//datatcps:數(shù)據(jù)連接套接字,通過(guò)它來(lái)接收數(shù)據(jù)
//filename:用于存放數(shù)據(jù)的文件名
int RecvFile(SOCKET datatcps, char* filename) {
?? ?char buf[1024];
?? ?FILE* file = fopen(filename, "wb");
?? ?if (!file) {
?? ??? ?printf("寫(xiě)入文件時(shí)發(fā)生未知錯(cuò)誤!\n");
?? ??? ?fclose(file);
?? ??? ?closesocket(datatcps);
?? ??? ?return 0;
?? ?}
?? ?printf("接受文件數(shù)據(jù)中。。。。。。");
?? ?while (1) {
?? ??? ?int r = recv(datatcps, buf, 1024, 0);
?? ??? ?if (r == SOCKET_ERROR) {
?? ??? ??? ?printf("從客戶(hù)端接受文件時(shí)發(fā)生未知錯(cuò)誤!\n");
?? ??? ??? ?fclose(file);
?? ??? ??? ?closesocket(datatcps);
?? ??? ??? ?return 0;
?? ??? ?}
?? ??? ?if (!r) {
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?fwrite(buf, 1, r, file);
?? ?}
?? ?fclose(file);
?? ?closesocket(datatcps);
?? ?printf("完成傳輸!\n");
?? ?return 1;
}
?
//檢測(cè)文件是否存在:
int FileExists(const char *filename)
{
?? ?WIN32_FIND_DATA fd;
?? ?if (FindFirstFile(filename, &fd) == INVALID_HANDLE_VALUE)
?? ??? ?return 0;
?? ?return 1;
}

3.客戶(hù)端

頭文件:(sizes.h)

#pragma once
?
//服務(wù)器偵聽(tīng)控制連接請(qǐng)求的端口
#define CMD_PORT 5858
//客戶(hù)機(jī)偵聽(tīng)數(shù)據(jù)連接請(qǐng)求的端口
#define DATA_PORT 5850
//命令報(bào)文參數(shù)緩存的大小
#define CMD_PARAM_SIZE 256
//回復(fù)報(bào)文消息緩存的大小
#define RSPNS_TEXT_SIZE 256
#define BACKLOG 10
#define DATA_BUFSIZE 4096
?
//命令類(lèi)型
typedef enum {
?? ?LS, PWD, CD, DOWN, UP, QUIT
} CmdID;
?
//命令報(bào)文,從客戶(hù)端發(fā)往服務(wù)器
typedef struct _CmdPacket {
?? ?CmdID cmdid;
?? ?char param[CMD_PARAM_SIZE];
} CmdPacket;
?
//回復(fù)報(bào)文的類(lèi)型
typedef enum {
?? ?OK, ERR
} RspnsID;
?
//回復(fù)報(bào)文,從服務(wù)器發(fā)往客戶(hù)端
typedef struct _RspnsPacket {
?? ?RspnsID rspnsid;
?? ?char text[RSPNS_TEXT_SIZE];
} RspnsPacket;

源文件:(客戶(hù)端.cpp)

#include <WinSock2.h>
#include <windows.h>
#include "sizes.h"
#include <tchar.h>
#include <iostream>
?
#pragma comment(lib, "ws2_32.lib")
?
//讀取回復(fù)報(bào)文
void do_read_rspns(SOCKET fd, RspnsPacket *ptr)
{
?? ?int count = 0;
?? ?int size = sizeof(RspnsPacket);
?? ?while (count < size)
?? ?{
?? ??? ?int nRead = recv(fd, (char *)ptr + count, size - count, 0);
?? ??? ?if (nRead <= 0)
?? ??? ?{
?? ??? ??? ?printf("讀取服務(wù)器的回復(fù)失?。n");
?? ??? ??? ?closesocket(fd);
?? ??? ??? ?exit(1);
?? ??? ?}
?? ??? ?count += nRead;
?? ?}
}
?
//發(fā)送命令報(bào)文
void do_write_cmd(SOCKET fd, CmdPacket *ptr)
{
?? ?int size = sizeof(CmdPacket);
?? ?int flag = send(fd, (char *)ptr, size, 0);
?? ?if (flag == SOCKET_ERROR)
?? ?{
?? ??? ?printf("給服務(wù)器發(fā)送命令失??!\n");
?? ??? ?closesocket(fd);
?? ??? ?WSACleanup();
?? ??? ?exit(1);
?? ?}
}
?
//創(chuàng)建數(shù)據(jù)連接套接字并進(jìn)入偵聽(tīng)狀態(tài)
SOCKET create_data_socket()
{
?? ?SOCKET sockfd;
?? ?struct sockaddr_in my_addr;
?? ?//創(chuàng)建用于數(shù)據(jù)連接的套接字
?? ?if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
?? ?{
?? ??? ?printf("創(chuàng)建用于數(shù)據(jù)連接的套接字失??!\n");
?? ??? ?WSACleanup();
?? ??? ?exit(1);
?? ?}
?? ?my_addr.sin_family = AF_INET;
?? ?my_addr.sin_port = htons(DATA_PORT);
?? ?my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
?? ?memset(&(my_addr.sin_zero), 0, sizeof(my_addr.sin_zero));
?
?? ?//綁定
?? ?if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
?? ?{
?? ??? ?int err = WSAGetLastError();
?? ??? ?printf("綁定地址失敗,錯(cuò)誤代碼:%d\n", err);
?? ??? ?closesocket(sockfd);
?? ??? ?WSACleanup();
?? ??? ?exit(1);
?? ?}
?
?? ?//偵聽(tīng)數(shù)據(jù)連接請(qǐng)求
?? ?if (listen(sockfd, 1) == SOCKET_ERROR)
?? ?{
?? ??? ?printf("監(jiān)聽(tīng)數(shù)據(jù)連接失??!\n");
?? ??? ?closesocket(sockfd);
?? ??? ?WSACleanup();
?? ??? ?exit(1);
?? ?}
?? ?return sockfd;
}
?
//處理list命令
void list(SOCKET sockfd)
{
?? ?int sin_size;
?? ?int nRead;
?? ?CmdPacket cmd_packet;
?? ?SOCKET newsockfd, data_sockfd;
?? ?struct sockaddr_in their_add;
?? ?char data_buf[DATA_BUFSIZE];
?
?? ?//創(chuàng)建數(shù)據(jù)連接
?? ?newsockfd = create_data_socket();
?? ?//構(gòu)建命令報(bào)文并發(fā)送至服務(wù)器
?? ?cmd_packet.cmdid = LS;//沒(méi)有參數(shù)
?? ?do_write_cmd(sockfd, &cmd_packet);
?? ?sin_size = sizeof(struct sockaddr_in);
?? ?//接受服務(wù)器的數(shù)據(jù)連接請(qǐng)求
?? ?if ((data_sockfd = accept(newsockfd, (struct sockaddr*)&their_add, &sin_size)) == INVALID_SOCKET)
?? ?{
?? ??? ?printf("獲取文件列表失敗!\n");
?? ??? ?closesocket(newsockfd);
?? ??? ?closesocket(sockfd);
?? ??? ?WSACleanup();
?? ??? ?exit(1);
?? ?}
?
?? ?//每次讀到多少數(shù)據(jù)就顯示多少,直到數(shù)據(jù)連接斷開(kāi)
?? ?while (true)
?? ?{
?? ??? ?nRead = recv(data_sockfd, data_buf, DATA_BUFSIZE - 1, 0);
?? ??? ?if (nRead == SOCKET_ERROR)
?? ??? ?{
?? ??? ??? ?printf("讀取服務(wù)器回復(fù)失??!\n");
?? ??? ??? ?closesocket(data_sockfd);
?? ??? ??? ?closesocket(newsockfd);
?? ??? ??? ?closesocket(sockfd);
?? ??? ??? ?WSACleanup();
?? ??? ??? ?exit(1);
?? ??? ?}
?
?? ??? ?if (nRead == 0)//數(shù)據(jù)讀取結(jié)束
?? ??? ??? ?break;
?
?? ??? ?//顯示數(shù)據(jù)
?? ??? ?data_buf[nRead] = '\0';
?? ??? ?printf("%s", data_buf);
?
?? ?}
?? ?closesocket(data_sockfd);
?? ?closesocket(newsockfd);
}
//處理pwd命令:
void pwd(int sockfd)
{
?? ?CmdPacket cmd_packet;
?? ?RspnsPacket rspns_packet;
?
?? ?cmd_packet.cmdid = PWD;
?? ?//發(fā)送命令報(bào)文并讀取回復(fù):
?? ?do_write_cmd(sockfd, &cmd_packet);
?? ?do_read_rspns(sockfd, &rspns_packet);
?? ?printf("%s\n", rspns_packet.text);
}
?
//處理cd命令:
void cd(int sockfd)
{
?? ?CmdPacket cmd_packet;
?? ?RspnsPacket rspns_packet;
?
?
?? ?cmd_packet.cmdid = CD;
?? ?scanf("%s", cmd_packet.param);
?
?? ?//發(fā)送命令報(bào)文并讀取回復(fù):
?? ?do_write_cmd(sockfd, &cmd_packet);
?? ?do_read_rspns(sockfd, &rspns_packet);
?? ?if (rspns_packet.rspnsid == ERR)
?? ??? ?printf("%s", rspns_packet.text);
}
?
?
//處理down命令,即下載文件:
void get_file(SOCKET sockfd)
{
?? ?FILE *fd;
?? ?char data_buf[DATA_BUFSIZE];
?
?? ?CmdPacket cmd_packet;
?? ?RspnsPacket rspns_packet;
?
?? ?SOCKET newsockfd, data_sockfd;
?? ?struct sockaddr_in their_addr;
?? ?int sin_size;
?? ?int count;
?
?? ?//設(shè)置命令報(bào)文:
?? ?cmd_packet.cmdid = DOWN;
?? ?scanf("%s", cmd_packet.param);
?
?? ?//打開(kāi)或者創(chuàng)建本地文件以供寫(xiě)數(shù)據(jù):
?? ?fd = fopen(cmd_packet.param, "wb");//使用二進(jìn)制方程
?? ?if (fd == NULL)
?? ?{
?? ??? ?printf("打開(kāi)文件%s來(lái)寫(xiě)入失??!\n", cmd_packet.param);
?? ??? ?return;
?? ?}
?
?? ?//創(chuàng)建數(shù)據(jù)連接并偵聽(tīng)服務(wù)器的連接請(qǐng)求:
?? ?newsockfd = create_data_socket();
?
?? ?//發(fā)送報(bào)文請(qǐng)求:
?? ?do_write_cmd(sockfd, &cmd_packet);
?
?? ?//讀取回復(fù)報(bào)文:
?? ?do_read_rspns(sockfd, &rspns_packet);
?? ?if (rspns_packet.rspnsid == ERR)
?? ?{
?? ??? ?printf("%s", rspns_packet.text);
?? ??? ?closesocket(newsockfd);
?
?? ??? ?fclose(fd);
?? ??? ?//刪除文件:
?? ??? ?DeleteFile(cmd_packet.param);
?? ??? ?return;
?? ?}
?
?? ?sin_size = sizeof(struct sockaddr_in);
?? ?//等待接受服務(wù)器的連接請(qǐng)求
?? ?if ((data_sockfd = accept(newsockfd, (struct sockaddr *)&their_addr, &sin_size)) == INVALID_SOCKET)
?? ?{
?? ??? ?printf("獲取文件失?。n");
?? ??? ?closesocket(newsockfd);
?
?? ??? ?fclose(fd);
?? ??? ?//刪除文件:
?? ??? ?DeleteFile(cmd_packet.param);
?? ??? ?return;
?? ?}
?
?? ?//循環(huán)讀取網(wǎng)絡(luò)數(shù)據(jù)并寫(xiě)入文件:
?? ?while ((count = recv(data_sockfd, data_buf, DATA_BUFSIZE, 0)) > 0)
?? ??? ?fwrite(data_buf, sizeof(char), count, fd);
?
?? ?closesocket(data_sockfd);
?? ?closesocket(newsockfd);
?? ?fclose(fd);
}
?
//處理put命令,即上傳文件
void put_file(SOCKET sockfd)
{
?? ?FILE *fd;
?? ?CmdPacket cmd_packet;
?? ?RspnsPacket rspns_packet;
?? ?char data_buf[DATA_BUFSIZE];
?
?? ?SOCKET newsockfd, data_sockfd;
?? ?struct sockaddr_in their_addr;
?? ?int sin_size;
?? ?int count;
?? ?cmd_packet.cmdid = UP;
?? ?scanf("%s", cmd_packet.param);
?
?? ?//打開(kāi)本地文件用于讀取數(shù)據(jù)
?? ?fd = fopen(cmd_packet.param, "rb");
?? ?if (fd == NULL)
?? ?{
?? ??? ?printf("打開(kāi)文件%s來(lái)讀取數(shù)據(jù)失??!\n", cmd_packet.param);
?? ??? ?return;
?? ?}
?
?? ?//創(chuàng)建數(shù)據(jù)連接套接字并進(jìn)入偵聽(tīng)狀態(tài);
?? ?newsockfd = create_data_socket();
?
?? ?//發(fā)送命令報(bào)文
?? ?do_write_cmd(sockfd, &cmd_packet);
?
?? ?//讀取回復(fù)報(bào)文
?? ?do_read_rspns(sockfd, &rspns_packet);
?? ?if (rspns_packet.rspnsid == ERR)
?? ?{
?? ??? ?printf("%s", rspns_packet.text);
?? ??? ?closesocket(newsockfd);
?? ??? ?fclose(fd);
?? ??? ?return;
?? ?}
?
?? ?sin_size = sizeof(struct sockaddr_in);
?? ?//準(zhǔn)備接受數(shù)據(jù)連接
?? ?if ((data_sockfd = accept(newsockfd, (struct sockaddr *)&their_addr, &sin_size)) == INVALID_SOCKET)
?? ?{
?? ??? ?printf("上傳文件傳輸錯(cuò)誤!\n");
?? ??? ?closesocket(newsockfd);
?? ??? ?fclose(fd);
?? ??? ?return;
?? ?}
?? ?//循環(huán)從文件中讀取數(shù)據(jù)并發(fā)給服務(wù)器
?? ?while (true)
?? ?{
?? ??? ?count = fread(data_buf, sizeof(char), DATA_BUFSIZE, fd);
?? ??? ?send(data_sockfd, data_buf, count, 0);
?? ??? ?if (count < DATA_BUFSIZE)//數(shù)據(jù)已經(jīng)讀完或者發(fā)生cuowu
?? ??? ??? ?break;
?? ?}
?
?? ?closesocket(data_sockfd);
?? ?closesocket(newsockfd);
?? ?fclose(fd);
}
?
//處理退出命令
void quit(int sockfd)
{
?? ?CmdPacket cmd_packet;
?? ?RspnsPacket rspns_packet;
?
?? ?cmd_packet.cmdid = QUIT;
?? ?do_write_cmd(sockfd, &cmd_packet);
?? ?do_read_rspns(sockfd, &rspns_packet);
?? ?printf("%s", rspns_packet.text);
?? ?getchar();
}
?
void main()
{
?? ?SOCKET sockfd;
?? ?struct sockaddr_in their_addr;
?? ?char cmd[10];
?? ?RspnsPacket rspns_packet;
?
?? ?WORD wVersionRequested;
?? ?WSADATA wsaData;
?? ?int err;
?? ?wVersionRequested = MAKEWORD(2, 2);
?? ?//Winsock初始化
?? ?err = WSAStartup(wVersionRequested, &wsaData);
?? ?if (err != 0)
?? ?{
?? ??? ?printf("WinSock初始化失??!\n");
?? ??? ?return;
?? ?}
?
?? ?//確認(rèn)WindSock DLL的版本是2.2
?? ?if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
?? ?{
?? ??? ?printf("WindSock版本不是2.2!\n");
?? ??? ?WSACleanup();
?? ??? ?return;
?? ?}
?
?? ?//創(chuàng)建用于控制諒解的socket
?? ?sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
?? ?if (sockfd == INVALID_SOCKET)
?? ?{
?? ??? ?printf("創(chuàng)建套接字失敗!\n");
?? ??? ?WSACleanup();
?? ??? ?exit(1);
?? ?}
?? ?their_addr.sin_family = AF_INET;
?? ?their_addr.sin_port = htons(CMD_PORT);
?? ?their_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
?? ?memset(&(their_addr.sin_zero), 0, sizeof(their_addr.sin_zero));
?
?? ?//連接服務(wù)器
?? ?if (connect(sockfd, (struct sockaddr*)&their_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
?? ?{
?? ??? ?printf("連接服務(wù)器失敗!\n");
?? ??? ?closesocket(sockfd);
?? ??? ?WSACleanup();
?? ??? ?exit(1);
?? ?}
?
?? ?//連接成功后,首先接受服務(wù)器發(fā)回的消息
?? ?do_read_rspns(sockfd, &rspns_packet);
?? ?printf("%s", rspns_packet.text);
?
?? ?//主循環(huán):讀取用戶(hù)輸入并分配執(zhí)行
?? ?while (true)
?? ?{
?? ??? ?scanf("%s", cmd);
?? ??? ?switch (cmd[0])
?? ??? ?{
?? ??? ?case 'l'://處理List命令
?? ??? ??? ?list(sockfd);
?? ??? ??? ?break;
?? ??? ?case 'p'://處理pwd命令
?? ??? ??? ?pwd(sockfd);
?? ??? ??? ?break;
?? ??? ?case 'c'://處理cd命令
?? ??? ??? ?cd(sockfd);
?? ??? ??? ?break;
?? ??? ?case 'd'://處理down命令
?? ??? ??? ?get_file(sockfd);
?? ??? ??? ?break;
?? ??? ?case 'u'://處理up命令
?? ??? ??? ?put_file(sockfd);
?? ??? ??? ?break;
?? ??? ?case 'q'://處理quit命令
?? ??? ??? ?quit(sockfd);
?? ??? ??? ?break;
?? ??? ?default:
?? ??? ??? ?printf("不存在的命令!\n");
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?if (cmd[0] == 'q')
?? ??? ??? ?break;
?? ?}
?? ?WSACleanup();
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論