#include <tchar.h> #include <winsock2.h> #include <string.h> #include <Ws2tcpip.h> #include #include<io.h> #pragma comment(lib,"ws2_32.lib")

#define BUFFER_SIZE 2048 // 定义文件缓冲区大小 #define FILE_NAME_MAX_SIZE 512 // 定义文件名最大长度

using namespace std; string home = "server_home/"; // 定义服务器存储文件的默认路径

// 函数声明 void receiveFile(SOCKET client_socket); void sendFile(SOCKET client_socket); void listFiles(SOCKET client_socket);

int main(int argc, char* argv[]) { // 初始化WSA,使得程序可以调用windows socket WORD sockVersion = MAKEWORD(2, 2); WSADATA wsaData; if (WSAStartup(sockVersion, &wsaData) != 0) { return 0; }

// 创建监听用套接字,server_socket,类型是TCP,并检测是否创建成功
SOCKET server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
	//如果创建的socket无效,则结束程序
	perror("socket error !\n");
	return 0;
}

//  创建地址,server_addr,并设置端口和IP
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
//端口号 8888
server_addr.sin_port = htons(8888);
//INADDR_ANY表示本机任意IP地址
server_addr.sin_addr.S_un.S_addr = INADDR_ANY;

//将socket与地址server_addr绑定
if (bind(server_socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
{
	perror("bind error !\n");
	return 0;
}

//server_socket开始监听
if (listen(server_socket, 20) == SOCKET_ERROR)
{
	perror("listen error !\n");
	return 0;
}

while (1)
{
	cout << "等待连接..." << endl;

	// 定义客户端的socket和socket地址结构
	SOCKET client_socket;
	sockaddr_in client_addr;
	int client_addr_length = sizeof(client_addr);

	// 接受连接请求,返回一个新的socket(描述符),这个新socket用于同连接的客户端通信 
	// accept函数会把连接到的客户端信息写到client_addr中 
	client_socket = accept(server_socket, (SOCKADDR*)&client_addr, &client_addr_length);
	if (client_socket == INVALID_SOCKET)
	{
		perror("Socket连接建立失败:\n");
		continue;
	}

	WCHAR IP_BUFFER[256] = TEXT("0");
	InetNtop(AF_INET, &client_addr.sin_addr, IP_BUFFER, 256);
	wcout << "Socket连接建立,客户端IP为" << IP_BUFFER << ",端口为:"
		<< ntohs(client_addr.sin_port) << endl;; // 宽字符记得用宽字符的方式进行输出

	// 接受客户端请求的指令
	// recv函数接收数据到缓冲区buffer中 
	char buffer[BUFFER_SIZE];
	memset(buffer, 0, BUFFER_SIZE);
	if (recv(client_socket, buffer, BUFFER_SIZE, 0) < 0)
	{
		perror("错误信息:接收客户端指令失败:\n");
		break;
	}
	char choice[2];
	strncpy_s(choice, buffer, strlen(buffer) > 1 ? 1 : strlen(buffer));

	// 客户端选择上传文件
	if (!strcmp(choice, "1"))
	{
		receiveFile(client_socket);
	}

	// 客户端选择下载文件
	else if (!strcmp(choice, "2"))
	{
		sendFile(client_socket);
	}

	// 客户端选择查看文件列表
	else if (!strcmp(choice, "3"))
	{
		listFiles(client_socket);
	}

	// 关闭与客户端的连接 
	closesocket(client_socket);
}

// 关闭监听用的socket 
closesocket(server_socket);
WSACleanup();
return 0;

}

// 接收文件函数 void receiveFile(SOCKET client_socket) { // 接收文件名 char buffer[BUFFER_SIZE]; memset(buffer, 0, BUFFER_SIZE); if (recv(client_socket, buffer, BUFFER_SIZE, 0) < 0) { perror("错误信息:接收客户端文件名失败!\n"); return; }

char file_name[FILE_NAME_MAX_SIZE + 1];
memset(file_name, 0, FILE_NAME_MAX_SIZE + 1);
strncpy_s(file_name, buffer, strlen(buffer) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));

// 接收客户端的状态:成功找到要上传的文件或没能找到文件
char stateNum[2];
memset(stateNum, 0, 2);
string flag; // 服务端状态

if (recv(client_socket, stateNum, 2, 0) < 0)
{
	cout << "错误信息:接收客户端状态失败!" << endl;
	flag = "0";
	send(client_socket, flag.c_str(), flag.length(), 0);
	return;
}

// 输出客户端状态
if (!strcmp(stateNum, "1"))
{
	cout << "错误信息:客户端未找到该文件名!" << endl;
	return;
}

flag = "1";
send(client_socket, flag.c_str(), flag.length(), 0);

// 准备写入文件
string f = file_name;
f = home + f;
FILE* fp;
errno_t F_ERR = fopen_s(&fp, f.c_str(), "wb");
if (F_ERR != 0)
{
	cout << "文件打开失败!" << endl;
	exit(1);
}

// 从服务器接收数据到buffer中 
// 每接收一段数据,便将其写入文件中,循环直到文件接收完并写完为止 
cout << "接收文件中..." << endl;
memset(buffer, 0, BUFFER_SIZE);
int length = 0;
while ((length = recv(client_socket, buffer, BUFFER_SIZE, 0)) > 0)
{
	if (fwrite(buffer, sizeof(char), length, fp) < length)
	{
		cout << "文件写入失败!" << endl;
		break;
	}
	memset(buffer, 0, BUFFER_SIZE);
}

cout << "文件接收成功!" << endl;
fclose(fp);

}

// 发送文件函数 void sendFile(SOCKET client_socket) { // 接收文件名 char buffer[BUFFER_SIZE]; memset(buffer, 0, BUFFER_SIZE); if (recv(client_socket, buffer, BUFFER_SIZE, 0) < 0) { perror("接收客户端文件名失败!\n"); return; } char file_name[FILE_NAME_MAX_SIZE + 1]; memset(file_name, 0, FILE_NAME_MAX_SIZE + 1); strncpy_s(file_name, buffer, strlen(buffer) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));

// 开始读取文件
string f = file_name;
f = home + f;
FILE* fp;
errno_t F_ERR = fopen_s(&fp, f.c_str(), "rb");
string stateNum;
if (F_ERR != 0)
{
	cout << "错误信息:未能找到该文件!" << endl;
	stateNum = "1";
	send(client_socket, stateNum.c_str(), stateNum.length(), 0);
	exit(1);
}
else
{
	stateNum = "2";
	send(client_socket, stateNum.c_str(), stateNum.length(), 0);
}
cout << "服务端开始传输文件!" << endl;
memset(buffer, 0, BUFFER_SIZE);

int length = 0;
// 每读取一段数据,便将其发送给客户端,循环直到文件读完为止 
while ((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
{
	if (send(client_socket, buffer, length, 0) < 0)
	{
		cout << "错误信息:文件传输失败!" << endl;
		break;
	}
	memset(buffer, 0, BUFFER_SIZE);
}

// 关闭文件 
fclose(fp);
cout << "文件传输成功!" << endl;

}

// 查看文件列表函数 void listFiles(SOCKET client_socket) { string path = "C:\Users\72797\source\repos\计算机网络\Debug\server_home\"; //文件句柄 long hFile = 0; //文件信息 struct _finddata_t fileinfo; string p; if ((hFile = _findfirst(p.assign(path).append("*").c_str(), &fileinfo)) != -1) { do { p.assign(fileinfo.name); if (p == "." || p == "..") continue; // 除本地目录和上级目录,排除

		memset(buffer, 0, BUFFER_SIZE);
		
		send(client_socket, p.c_str(), p.length(), 0);

	} while (_findnext(hFile, &fileinfo) == 0);
	_findclose(hFile);
}

}


原文地址: https://www.cveoy.top/t/topic/pF0z 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录