项目是用C++语言完成以下文件传输程序。
现在有客户端和服务端代码但是运行不起来,没显示报错呀 ,实在是不知道咋改了
环境是Visual Studio 2022 社区版
文件服务器提供文件下载的服务器,在一个端口进行监听,通过接受客户端的命令实现相应的行为:例如发送相应的文件给客户端。客户端连接到服务器的端口,通过输入命令行可以得到服务器的文件列表,并且可以通过命令行下载服务器上的文件。
实现以下功能,:
1.服务器命令行运行:FileServer.exe D:/fileFolder
FileServer.exe 是文件服务器的程序,后面的参数表示共享的文件夹。文件夹中可以事先准备一些文件。
客户端命令行启动:FileClient.exe 127.0.0.1 8080
2.FileClient.exe 是客户端程序,127.0.0.1是服务器的IP地址;8080是需要连接的服务器端口
3. 客户端可以通过下载命令下载服务器上的文件
下载的文件可以保存在客户端运行的当前目录当中。如果在一个机器上运行,客户端和服务器不要在同一个目录下运行,可能产生文件冲突。
4. 可以通过命令获服务器的文件列表
服务器返回的服务器共享文件夹中的文件列表.
返回格式可以自定义,例子中前面是文件名,后面是文件大小
5. 断线续传:当文件传输过程中意外短线或者异常退出导致文件未传输完成,下一次传输相同文件的时候可以从中断的位置开始传输;
6. 可以切换服务器上的当前目录,例如通过 cd 命令进入到共享目录的子目录,并对其进行文件列表和下载;
7. 简单的用户验证功能:用户名和密码
服务端代码
#include <WinSock2.h>
#include <iostream>
#include <thread>
#include <fstream>
#include <sstream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
// 客户端请求的命令
enum class RequestCommand
{
ListFiles = 1, // 列出文件列表
DownloadFile, // 下载文件
};
// 发送文件的线程函数
void SendFile(SOCKET clientSock, const char* filePath, int start = 0)
{
// 打开文件,判断是否成功
ifstream file(filePath, ios::binary);
if (!file)
{
cerr << "Cannot open file: " << filePath << endl;
return;
}
// 定位文件流的位置
file.seekg(start, ios::beg);
// 发送文件流
char buffer[1024];
int len = 0;
while (file.read(buffer, sizeof(buffer)))
{
len = send(clientSock, buffer, file.gcount(), 0);
if (len <= 0)
{
cerr << "Send file error." << endl;
break;
}
}
// 发送最后一块不满 buffer 的数据块
len = send(clientSock, buffer, file.gcount(), 0);
if (len <= 0)
{
cerr << "Send file error." << endl;
return;
}
cout << "File " << filePath << " sent successfully." << endl;
}
// 获取文件列表的函数,返回格式可以自定义
string GetFileList(const char* folderPath)
{
ostringstream oss;
oss << "Files in " << folderPath << ":" << endl;
// 遍历目录下的所有文件
WIN32_FIND_DATAA findData;
HANDLE handle = FindFirstFileA((string(folderPath) + "/*").c_str(), &findData);
if (handle != INVALID_HANDLE_VALUE)
{
do
{
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) // 不是目录
{
oss << findData.cFileName << "\t" << findData.nFileSizeLow << endl; // 输出文件名和文件大小
}
} while (FindNextFileA(handle, &findData));
FindClose(handle);
}
return oss.str();
}
// 处理客户端请求的线程函数
void HandleClient(SOCKET clientSock, const char* folderPath)
{
int len = 0;
RequestCommand cmd;
// 读取请求的命令
len = recv(clientSock, (char*)&cmd, sizeof(cmd), 0);
if (len <= 0)
{
cerr << "Error: no command received." << endl;
return;
}
switch (cmd)
{
case RequestCommand::ListFiles:
{
string fileList = GetFileList(folderPath);
len = send(clientSock, fileList.c_str(), fileList.size(), 0); // 发送文件列表
if (len <= 0)
{
cerr << "Send file list error." << endl;
return;
}
break;
}
case RequestCommand::DownloadFile:
{
char fileName[256];
int startPos;
// 读取需要下载的文件名和起始位置
len = recv(clientSock, fileName, sizeof(fileName), 0);
if (len <= 0)
{
cerr << "Error: no file name received." << endl;
return;
}
len = recv(clientSock, (char*)&startPos, sizeof(startPos), 0);
if (len <= 0)
{
cerr << "Error: no start position received." << endl;
return;
}
// 发送文件
SendFile(clientSock, (string(folderPath) + "/" + fileName).c_str(), startPos);
break;
}
default:
cerr << "Error: unknown command received." << endl;
break;
}
}
int main(int argc, char* argv[])
{
if (argc != 2)
{
cout << "Usage: FileServer.exe folderPath" << endl;
return 0;
}
const char* folderPath = argv[1];
// 初始化 Winsock
WSADATA wsaData;
int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (err != 0)
{
cerr << "WSAStartup error: " << err << endl;
return 1;
}
// 创建套接字
SOCKET listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSock == INVALID_SOCKET)
{
cerr << "Error creating socket: " << WSAGetLastError() << endl;
WSACleanup();
return 1;
}
// 绑定端口
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
err = bind(listenSock, (SOCKADDR*)&addr, sizeof(addr));
if (err == SOCKET_ERROR)
{
cerr << "Error binding port: " << WSAGetLastError() << endl;
closesocket(listenSock);
WSACleanup();
return 1;
}
// 监听端口
err = listen(listenSock, SOMAXCONN);
if (err == SOCKET_ERROR)
{
cerr << "Error listening: " << WSAGetLastError() << endl;
closesocket(listenSock);
WSACleanup();
return 1;
}
cout << "File server started." << endl;
while (true)
{
// 等待客户端连接
SOCKADDR_IN clientAddr;
int addrLen = sizeof(clientAddr);
SOCKET clientSock = accept(listenSock, (SOCKADDR*)&clientAddr, &addrLen);
if (clientSock == INVALID_SOCKET)
{
cerr << "Error accepting socket: " << WSAGetLastError() << endl;
continue;
}
// 创建新线程处理客户端请求
thread t(HandleClient, clientSock, folderPath);
t.detach();
}
// 关闭监听套接字
closesocket(listenSock);
WSACleanup();
return 0;
}
```c++
客户端代码
#include <WinSock2.h>
#include <iostream>
#include <fstream>
#include <thread>
#include <conio.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
// 服务器端口
const int SERVER_PORT = 8080;
// 服务器返回的文件列表
struct FileItem
{
char name[256];
int size;
};
int main(int argc, char* argv[])
{
if (argc != 3)
{
cout << "Usage: FileClient.exe serverIP username" << endl;
return 0;
}
const char* serverIP = argv[1];
const char* username = argv[2];
// 初始化 Winsock
WSADATA wsaData;
int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (err != 0)
{
cerr << "WSAStartup error: " << err << endl;
return 1;
}
// 创建套接字
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
cerr << "Error creating socket: " << WSAGetLastError() << endl;
WSACleanup();
return 1;
}
// 连接服务器
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(SERVER_PORT);
addr.sin_addr.s_addr = inet_addr(serverIP);
err = connect(sock, (SOCKADDR*)&addr, sizeof(addr));
if (err == SOCKET_ERROR)
{
cerr << "Error connecting: " << WSAGetLastError() << endl;
closesocket(sock);
WSACleanup();
return 1;
}
// 发送用户名和密码
char buffer[256];
sprintf_s(buffer, sizeof(buffer), "%s", username);
int len = send(sock, buffer, strlen(buffer) + 1, 0);
if (len <= 0)
{
cerr << "Send username error." << endl;
closesocket(sock);
WSACleanup();
return 1;
}
// 输入密码(不回显)
cout << "Enter password: ";
char password[256];
int i = 0;
char ch = _getch();
while (ch != 13) // 回车结束输入
{
if (ch == 8 && i > 0) // 退格
{
i--;
cout << "\b \b"; // 删除一个字符
}
else if (ch >= ' ' && ch <= '~' && i < sizeof(password) - 1) // 输入可见字符
{
password[i] = ch;
i++;
cout << "*"; // 输出*代替
}
ch = _getch();
}
password[i] = '\0';
// 发送密码(使用 XOR 加密)
for (i = 0; i < strlen(password); i++)
{
password[i] ^= 0x5A;
}
len = send(sock, password, strlen(password) + 1, 0);
if (len <= 0)
{
cerr << "Send password error." << endl;
closesocket(sock);
WSACleanup();
return 1;
}
// 显示命令提示符并等待命令
while (true)
{
cout << "> ";
cin.getline(buffer, sizeof(buffer)); // 读取一行命令
if (strcmp(buffer, "quit") == 0) // 退出
{
break;
}
else if (strcmp(buffer, "ls") == 0) // 列出文件列表
{
// 发送列表命令
int cmd = (int)RequestCommand::ListFiles;
len = send(sock, (char*)&cmd, sizeof(cmd), 0);
if (len <= 0)
{
cerr << "Send command error." << endl;
break;
}
// 接收文件列表
char fileList[1024];
len = recv(sock, fileList, sizeof(fileList), 0);
if (len <= 0)
{
cerr << "Receive file list error." << endl;
break;
}
cout << fileList;
}
else if (strncmp(buffer, "cd ", 3) == 0) // 切换目录
{
cout << "Unsupported command: " << buffer << endl; // TODO: 实现切换目录命令
}
else if (strncmp(buffer, "get ", 4) == 0) // 下载文件
{
char fileName[256];
int startPos;
// 解析命令
sscanf_s(buffer, "get %s %d", fileName, (unsigned)_countof(fileName), &startPos);
// 发送下载命令
int cmd = (int)RequestCommand::DownloadFile;
len = send(sock, (char*)&cmd, sizeof(cmd), 0);
if (len <= 0)
{
cerr << "Send command error." << endl;
break;
}
// 发送文件名和起始位置
len = send(sock, fileName, strlen(fileName) + 1, 0);
if (len <= 0)
{
cerr << "Send file name error." << endl;
break;
}
len = send(sock, (char*)&startPos, sizeof(startPos), 0);
if (len <= 0)
{
cerr << "Send start position error." << endl;
break;
}
// 接收文件流
ofstream file(fileName, ios::binary | ios::app); // 追加方式打开文件
if (!file)
{
cerr << "Cannot open file: " << fileName << endl;
break;
}
char buffer[1024];
int size = 0;
while ((size = recv(sock, buffer, sizeof(buffer), 0)) > 0)
{
file.write(buffer, size);
}
file.close();
cout << "File " << fileName << " downloaded successfully." << endl;
}
else
{
cout << "Unknown command: " << buffer << endl;
}
}
// 关闭套接字
closesocket(sock);
WSACleanup();
return 0;
}
```
客户端和服务器之间采用tcp的方式进行的通讯。你现在客户端和服务器是运行同一台电脑上吗?
你应该是想骗答案吧,你这个问题我看见了3个了,都没有采纳,然而你的代码就是那里复制来的。
https://ask.csdn.net/questions/7958399
服务端
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
using namespace std;
int main(int argc, char *argv[]) {
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <port>" << endl;
return 1;
}
int port = atoi(argv[1]);
// 创建socket
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
cerr << "Failed to create socket" << endl;
return 1;
}
// 设置socket地址
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
// 绑定socket
if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
cerr << "Failed to bind socket" << endl;
return 1;
}
// 监听socket
if (listen(server_fd, 5) == -1) {
cerr << "Failed to listen on socket" << endl;
return 1;
}
cout << "Server is listening on port " << port << endl;
while (true) {
// 接受客户端连接
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_addr_len);
if (client_fd == -1) {
cerr << "Failed to accept client connection" << endl;
continue;
}
cout << "Client " << inet_ntoa(client_addr.sin_addr) << " connected" << endl;
// 接受文件名
char filename[256];
memset(filename, 0, sizeof(filename));
if (recv(client_fd, filename, sizeof(filename), 0) == -1) {
cerr << "Failed to receive filename" << endl;
close(client_fd);
continue;
}
cout << "Received filename: " << filename << endl;
// 打开文件
ifstream file(filename, ios::binary);
if (!file.is_open()) {
cerr << "Failed to open file: " << filename << endl;
close(client_fd);
continue;
}
// 发送文件内容
char buffer[1024];
while (file.read(buffer, sizeof(buffer)).gcount() > 0) {
if (send(client_fd, buffer, file.gcount(), 0) == -1) {
cerr << "Failed to send file content" << endl;
break;
}
}
// 关闭文件和socket
file.close();
close(client_fd);
cout << "File transfer completed" << endl;
}
// 关闭socket
close(server_fd);
return 0;
}
客户端
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
using namespace std;
int main(int argc, char *argv[]) {
if (argc != 3) {
cerr << "Usage: " << argv[0] << " <server_ip> <server_port>" << endl;
return 1;
}
const char* server_ip = argv[1];
int server_port = atoi(argv[2]);
// 创建socket
int client_fd = socket(AF_INET, SOCK_STREAM, 0);
if (client_fd == -1) {
cerr << "Failed to create socket" << endl;
return 1;
}
// 设置socket地址
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(server_ip);
server_addr.sin_port = htons(server_port);
// 连接服务器
if (connect(client_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
cerr << "Failed to connect to server" << endl;
return 1;
}
cout << "Connected to server " << server_ip << " on port " << server_port << endl;
// 发送文件名
char filename[256];
cout << "Enter filename: ";
cin.getline(filename, sizeof(filename));
if (send(client_fd, filename, strlen(filename) + 1, 0) == -1) {
cerr << "Failed to send filename" << endl;
close(client_fd);
return 1;
}
// 接受文件内容
char buffer[1024];
ofstream file(filename, ios::binary);
if (!file.is_open()) {
cerr << "Failed to create file: " << filename << endl;
close(client_fd);
return 1;
}
while (true) {
int count = recv(client_fd, buffer, sizeof(buffer), 0);
if (count == -1) {
cerr << "Failed to receive file content" << endl;
break;
}
if (count == 0) {
break;
}
file.write(buffer, count);
}
// 关闭文件和socket
file.close();
close(client_fd);
cout << "File transfer completed" << endl;
return 0;
}
类似这样的
ofstream fout("test.txt");
fout << "666" << endl;
文件传输系统无报错代码但是无法运行,说明可能是代码逻辑是出现了问题,导致程序进行文件传输时,没有真正的进入到文件传输的过程,原因常见的有,没有写调用真正的文件传输的代码,条件语句写错了导致进入到其他代码分枝,传输不成功,报错了但是被异常捕获了,或者一直卡在传输文件的代码块。因此,需要检查你的代码,可以使用调试或打印的方法,逐步逐行定位问题所在。
抓包看一下客户端与服务器之间有没有发送网络通信
参考 Chatgpt Plus版本:
于Winsock的C++ TCP服务器的代码示例。该服务器可以接受来自客户端的连接,并处理客户端的请求。主要功能包括: 初始化WinSock:使用WSAStartup函数初始化WinSock库。 创建服务器套接字:使用socket函数创建一个服务器套接字。 绑定服务器套接字:使用bind函数将服务器套接字绑定到指定的IP地址和端口号。 监听客户端连接:使用listen函数监听客户端的连接请求。 接受客户端连接:使用accept函数接受客户端的连接请求,并创建一个新的套接字与客户端进行通信。 处理客户端请求:在单独的线程中处理客户端的请求。根据客户端发送的命令,执行相应的操作,如发送文件列表或下载文件。 关闭套接字:在适当的时候关闭服务器套接字和客户端套接字。 清理WinSock:使用WSACleanup函数清理WinSock库。
#include <WinSock2.h>
#include <iostream>
#include <thread>
#include <fstream>
#include <sstream>
#include <cstring> // 添加头文件
#pragma comment(lib, "ws2_32.lib")
using namespace std;
// 客户端请求的命令
enum class RequestCommand
{
ListFiles = 1, // 列出文件列表
DownloadFile, // 下载文件
};
// 发送文件的线程函数
void SendFile(SOCKET clientSock, const char* filePath, int start = 0)
{
// 打开文件,判断是否成功
ifstream file(filePath, ios::binary);
if (!file)
{
cerr << "Cannot open file: " << filePath << endl;
return;
}
// 定位文件流的位置
file.seekg(start, ios::beg);
// 发送文件流
char buffer[1024];
int len = 0;
while (file.read(buffer, sizeof(buffer)))
{
len = send(clientSock, buffer, file.gcount(), 0);
if (len <= 0)
{
cerr << "Send file error." << endl;
break;
}
}
// 发送最后一块不满 buffer 的数据块
len = send(clientSock, buffer, file.gcount(), 0);
if (len <= 0)
{
cerr << "Send file error." << endl;
return;
}
cout << "File " << filePath << " sent successfully." << endl;
}
// 获取文件列表的函数,返回格式可以自定义
string GetFileList(const char* folderPath)
{
ostringstream oss;
oss << "Files in " << folderPath << ":" << endl;
// 遍历目录下的所有文件
WIN32_FIND_DATAA findData;
HANDLE handle = FindFirstFileA((string(folderPath) + "/*").c_str(), &findData);
if (handle != INVALID_HANDLE_VALUE)
{
do
{
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) // 不是目录
{
oss << findData.cFileName << "\t" << findData.nFileSizeLow << endl; // 输出文件名和文件大小
}
} while (FindNextFileA(handle, &findData));
FindClose(handle);
}
return oss.str();
}
// 处理客户端请求的线程函数
void HandleClient(SOCKET clientSock, const char* folderPath)
{
int len = 0;
RequestCommand cmd;
// 读取请求的命令
len = recv(clientSock, (char*)&cmd, sizeof(cmd), 0);
if (len <= 0)
{
cerr << "Error: no command received." << endl;
return;
}
switch (cmd)
{
case RequestCommand::ListFiles:
{
string fileList = GetFileList(folderPath);
len = send(clientSock, fileList.c_str(), fileList.size(), 0); // 发送文件列表
if (len <= 0)
{
cerr << "Error sending file list." << endl;
}
break;
}
case RequestCommand::DownloadFile:
{
// 读取文件名
char fileName[256];
len = recv(clientSock, fileName, sizeof(fileName), 0);
if (len <= 0)
{
cerr << "Error receiving file name." << endl;
return;
}
// 构造文件路径
string filePath = string(folderPath) + "/" + fileName;
// 检查文件是否存在
ifstream file(filePath, ios::binary);
if (!file)
{
cerr << "File not found: " << filePath << endl;
return;
}
// 获取文件大小
file.seekg(0, ios::end);
int fileSize = file.tellg();
file.seekg(0, ios::beg);
// 发送文件大小
len = send(clientSock, (char*)&fileSize, sizeof(fileSize), 0);
if (len <= 0)
{
cerr << "Error sending file size." << endl;
return;
}
// 接收客户端的起始位置
int start = 0;
len = recv(clientSock, (char*)&start, sizeof(start), 0);
if (len <= 0)
{
cerr << "Error receiving start position." << endl;
return;
}
// 发送文件
SendFile(clientSock, filePath.c_str(), start);
break;
}
default:
cerr << "Unknown command." << endl;
break;
}
// 关闭客户端连接
closesocket(clientSock);
}
int main()
{
// 初始化 WinSock
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
cerr << "Failed to initialize winsock." << endl;
return -1;
}
// 创建服务器端套接字
SOCKET serverSock = socket(AF_INET, SOCK_STREAM, 0);
if (serverSock == INVALID_SOCKET)
{
cerr << "Failed to create socket." << endl;
WSACleanup();
return -1;
}
// 绑定服务器端套接字
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888); // 服务器端口号
serverAddr.sin_addr.s_addr = INADDR_ANY;
if (bind(serverSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
cerr << "Failed to bind socket." << endl;
closesocket(serverSock);
WSACleanup();
return -1;
}
// 监听客户端连接
if (listen(serverSock, SOMAXCONN) == SOCKET_ERROR)
{
cerr << "Failed to listen." << endl;
closesocket(serverSock);
WSACleanup();
return -1;
}
cout << "Server started. Waiting for connections..." << endl;
while (true)
{
// 接受客户端连接
sockaddr_in clientAddr;
int addrLen = sizeof(clientAddr);
SOCKET clientSock = accept(serverSock, (sockaddr*)&clientAddr, &addrLen);
if (clientSock == INVALID_SOCKET)
{
cerr << "Accept failed." << endl;
closesocket(serverSock);
WSACleanup();
return -1;
}
// 打印客户端地址
char ip[16];
inet_ntop(AF_INET, &(clientAddr.sin_addr), ip, sizeof(ip));
cout << "Client connected: " << ip << endl;
// 创建线程处理客户端请求
thread t(ProcessClientRequest, clientSock);
// 分离线程,让其自主执行
t.detach();
}
// 关闭服务器套接字
closesocket(serverSock);
// 清理 WinSock
WSACleanup();
return 0;
}