开发环境:
操作系统:Windows 11
IDE:Visual Studio 2022
编程语言:C/C++
实验要求:
程序一“基于 TCP 的可靠文件传输”,功能包括:
- 在客户端,用户选择本地的某个文件,并发送到服务器端。
- 在服务器端,接收客户端传输的数据流,并按 IP 地址保存在服务器端(文件名重复的,可以覆盖)。
- 如果传输过程中服务器端发现客户端断开,服务器端应删除文件,并在屏 幕上提示,如“IP:1.2.3.4 发来 abcd.txt 文件过程中失去连接。”。
- 如果客户端发 现服务器端不工作,客户端应有提示“服务器 1.2.3.5:62345 失去连接”。
程序二“基于 UDP 的不可靠文件传输”,
- 功能同上,但不能使用 TCP 协议进行传输。考虑如果传输过程中服务器端、客户端如何发现断开。
程序演示:
程序一:
发送中途关闭客户端
发送中途关闭服务端
程序二:
发送过程中客户端关闭
emm……UDP的客户端 判断 服务端关闭没做,客户端只管发送,才不管服务端接受没。至于服务端判断客户端失去连接,是通过接收超时判断的。
代码:
程序一Server:
#define _CRT_SECURE_NO_WARNINGS
#include <ws2tcpip.h>
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define DEFAULT_PORT "54321"
#define BUFFER_SIZE 1024
int main() {
// 初始化库
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
printf("WSAStartup failed with error: %d\n", result);
return 1;
}
// 创建套接字
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET) {
printf("Could not create socket: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
// 绑定IP和端口
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(atoi(DEFAULT_PORT));
if (bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
printf("Bind failed with error: %d\n", WSAGetLastError());
closesocket(serverSocket);
WSACleanup();
return 1;
}
// 开始监听
if (listen(serverSocket, 5) == SOCKET_ERROR) {
printf("Listen failed with error: %d\n", WSAGetLastError());
closesocket(serverSocket);
WSACleanup();
return 1;
}
printf("Server listening on port %s...\n\n", DEFAULT_PORT);
// 循环接收文件
while (1)
{
SOCKADDR clientAddr;
int clientAddrSize = sizeof(clientAddr);
// 从已完成连接队列返回下一个建立成功的连接
SOCKET clientSocket = accept(serverSocket, &clientAddr, &clientAddrSize);
if (clientSocket == INVALID_SOCKET) {
printf("Accept failed with error: %d\n", WSAGetLastError());
closesocket(serverSocket);
WSACleanup();
return 1;
}
printf("一个客户端连接成功!\n\n");
char buffer[BUFFER_SIZE + 1] = { 0 };
// 接收 文件大小 和 文件名
char fileNameAndExt[MAX_PATH * 4];
int fileSize = 0;
int receivedBytes = recv(clientSocket, buffer, BUFFER_SIZE, 0);
if (receivedBytes == SOCKET_ERROR) {
int error = WSAGetLastError();
if (error == WSAECONNRESET) {
printf("Client connection reset by peer.\n");
break;
}
else if (error == WSAETIMEDOUT) {
printf("Receive timeout.\n");
break;
}
else {
printf("Send failed with error: %d\n", error);
break;
}
}
else if (receivedBytes == 0) {
printf("Connection closed by client.\n");
break;
}
else {
// 取出文件大小(前4个字节),文件名
fileSize = (((unsigned char)buffer[0]) << 24) |
(((unsigned char)buffer[1]) << 16) |
(((unsigned char)buffer[2]) << 8) |
((unsigned char)buffer[3]);
strcpy(fileNameAndExt, buffer + 4);
printf("接收到文件:%s\n", fileNameAndExt);
printf("文件大小:%d\n", fileSize);
}
// 打开文件,准备写入
FILE* pFile = fopen(fileNameAndExt, "wb");
if (pFile != NULL)
{
bool success = true;// 文件是否完全接收
int receivedSize = 0;// 已接收的字节数
// 循环接收文件,直到指定大小
while (1)
{
receivedBytes = recv(clientSocket, buffer, BUFFER_SIZE, 0);
if (receivedBytes == SOCKET_ERROR) {
success = false;
int error = WSAGetLastError();
if (error == WSAECONNRESET) {
// 连接断开:输出 客户端IP、端口,删除文件
char clientIP[INET_ADDRSTRLEN];
int clientPort;
struct sockaddr_in addr;
int addrLen = sizeof(addr);
if (getpeername(clientSocket, (struct sockaddr*)&addr, &addrLen) == 0)
{
inet_ntop(AF_INET, &addr.sin_addr, clientIP, INET_ADDRSTRLEN);
clientPort = ntohs(addr.sin_port);
}
else
printf("Error getting peer name: %d\n", WSAGetLastError());
printf("客户端 %s : %d 发来%s 文件过程中失去连接.\n", clientIP, clientPort, fileNameAndExt);
break;
}
else if (error == WSAETIMEDOUT) {
printf("Receive timeout.\n");
break;
}
else {
printf("Send failed with error: %d\n", error);
break;
}
}
else {
// 将缓冲区中的数据写入本地文件
if (fwrite(buffer, 1, receivedBytes, pFile) != receivedBytes)
{
printf("写入失败.\n");
break;
}
// 接收到指定大小,即认为文件接收成功
receivedSize += receivedBytes;
if (receivedSize == fileSize)
{
printf("%s 接收成功!\n\n\n", fileNameAndExt);
break;
}
}
}
// 关闭本地文件
fclose(pFile);
// 文件未能接收完全,删除之
if (!success)
{
remove(fileNameAndExt);
printf("%s 已删除.\n\n\n", fileNameAndExt);
}
}
else
{
printf("文件打开失败.\n\n\n");
}
closesocket(clientSocket);
}
closesocket(serverSocket);
WSACleanup();
system("pause");
return 0;
}
程序一Client:
#define _CRT_SECURE_NO_WARNINGS
#include <ws2tcpip.h>
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define DEFAULT_PORT "54321"
#define SERVER_IP "127.0.0.1" // 假设服务器在本地运行
#define BUFFER_SIZE 1024
// 这个类,是为了实现文件选择的。
class ChooseFile
{
private:
WCHAR name[MAX_PATH];
WCHAR ext[MAX_PATH];
char fileName_[MAX_PATH * 2];
char fileExt_[MAX_PATH * 2];
int fileSize;
public:
char fileSizeAndName[MAX_PATH * 4 + 4];
HANDLE hFile;
int fileNameSize;
char fileName[MAX_PATH * 4];
ChooseFile()
{
hFile = Choose(name, ext);
ConvertWCHARtoCHAR(name, fileName_, MAX_PATH * 2);
ConvertWCHARtoCHAR(ext, fileExt_, MAX_PATH * 2);
strPlusStr(fileName_, fileExt_, fileName);
fileNameSize = strlen(fileName);
// 将filesize添加到char数组的前面
unsigned bytes[4];
bytes[0] = (fileSize >> 24) & 0xFF;
bytes[1] = (fileSize >> 16) & 0xFF;
bytes[2] = (fileSize >> 8) & 0xFF;
bytes[3] = fileSize & 0xFF;
strcpy(fileSizeAndName + 4, fileName);
for (int i = 0; i < 4; i++)
{
fileSizeAndName[i] = bytes[i];
}
int temp = (bytes[0] << 24) |
(bytes[1] << 16) |
(bytes[2] << 8) |
bytes[3];
printf("文件名:%s\n", fileSizeAndName + 4);
printf("文件大小: %d\n", fileSize);
}
private:
void ConvertWCHARtoCHAR(const WCHAR* src, char* dest, int destSize) {
WideCharToMultiByte(CP_ACP, 0, src, -1, dest, destSize, NULL, NULL);
}
void strPlusStr(char* front, char* behind, char* dest)
{
// 计算合并后字符串的长度(包括结束符'\0')
int len1 = strlen(front);
int len2 = strlen(behind);
int total_len = len1 + len2 + 1; // 加1是为了结束符'\0'
// 将str1复制到merged_str
strcpy(dest, front);
// 将str2追加到merged_str的末尾
strcpy(dest + len1, behind);
}
HANDLE Choose(WCHAR* fileName, WCHAR* fileExt)
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL; // 或者设置为你的窗口句柄
ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0\0";// 设置了文件类型过滤器,允许用户选择文本文件或所有文件
ofn.nFilterIndex = 1;
ofn.lpstrFile = new WCHAR[MAX_PATH]; // 分配足够的空间存储文件路径
ZeroMemory(ofn.lpstrFile, MAX_PATH * sizeof(WCHAR)); // 确保缓冲区被清零
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = L"txt";// 设置了默认的文件扩展名为.txt
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn) == TRUE)
{
// 用户选择了文件,ofn.lpstrFile现在包含文件路径
printf("选择文件成功!\n");
// 提取文件名和扩展名
_wsplitpath_s(ofn.lpstrFile, NULL, 0, NULL, 0, fileName, MAX_PATH, fileExt, MAX_PATH);
// ... 接下来读取文件内容
HANDLE hFile = CreateFileW(
ofn.lpstrFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
fileSize = GetFileSize(hFile, NULL);
return hFile;
}
fileSize = 0;
return NULL;
}
}
};
int main() {
char serverIP[16];
printf("请输入 服务器IP:\n");
scanf("%s", serverIP);
// 初始化库
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
printf("WSAStartup failed with error: %d\n", result);
return 1;
}
// 创建套接字
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET) {
printf("Could not create socket: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
// 选择 要发送的文件
ChooseFile file;// 构造函数中,就已经选定了文件
// 发起3次握手,连接到服务器
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
int addrInfoSize = sizeof(serverAddr.sin_addr);
if (inet_pton(AF_INET, serverIP, &(serverAddr.sin_addr)) <= 0) {
printf("Invalid address/ Address not supported \n");
return 1;
}
serverAddr.sin_port = htons(atoi(DEFAULT_PORT));
if (connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
printf("Connect failed with error: %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
system("pause");
return 1;
}
printf("成功连接到服务器!\n");
// 发送文件大小 和 文件名
int sentBytes = send(
clientSocket,
(char*)&file.fileSizeAndName,
file.fileNameSize + 5,// 文件大小4个字节,字符串结束标志1个字节
0);
if (sentBytes == SOCKET_ERROR)
{
int error = WSAGetLastError();
if (error == WSAECONNRESET)
{
char serverIP[INET_ADDRSTRLEN];
int serverPort;
struct sockaddr_in addr;
int addrLen = sizeof(addr);
if (getpeername(clientSocket, (struct sockaddr*)&addr, &addrLen) == 0)
{
inet_ntop(AF_INET, &addr.sin_addr, serverIP, INET_ADDRSTRLEN);
serverPort = ntohs(addr.sin_port);
}
else
printf("Error getting peer name: %d\n", WSAGetLastError());
printf("服务器 %s : %d失去连接.\n", serverIP, serverPort);
}
else
printf("Send failed with error: %d\n", error);
// 发送失败(文件名都发送失败了,还有什么好说的,直接结束程序)
closesocket(clientSocket);
WSACleanup();
system("pause");
return 0;
}
else
{
printf("正在发送%s\n", file.fileName);
}
// 稍等一会,等待服务端取走缓冲区中的 文件大小 和 文件名
Sleep(100);
// 循环读取文件内容到缓冲区 并 发送之
char buffer[BUFFER_SIZE];
DWORD dwBytesRead;
bool success = true;// 全部发送成功 标志
while (ReadFile(file.hFile, buffer, BUFFER_SIZE, &dwBytesRead, NULL) && dwBytesRead > 0)
{
// 处理缓冲区中的数据,比如发送到服务器
sentBytes = send(clientSocket, buffer, dwBytesRead, 0);
if (sentBytes == SOCKET_ERROR)
{
success = false;
int error = WSAGetLastError();
if (error == WSAECONNRESET)
{
char serverIP[INET_ADDRSTRLEN];
int serverPort;
struct sockaddr_in addr;
int addrLen = sizeof(addr);
if (getpeername(clientSocket, (struct sockaddr*)&addr, &addrLen) == 0)
{
inet_ntop(AF_INET, &addr.sin_addr, serverIP, INET_ADDRSTRLEN);
serverPort = ntohs(addr.sin_port);
}
else
{
printf("Error getting peer name: %d\n", WSAGetLastError());
break;
}
printf("服务器 %s : %d失去连接\n", serverIP, serverPort);
break;
}
else
{
printf("Send failed with error: %d\n", error);
break;
}
}
}
if (success)
printf("文件发送成功\n\n");
closesocket(clientSocket);
WSACleanup();
system("pause");
return 0;
}
程序二Server:
#define _CRT_SECURE_NO_WARNINGS
#include <ws2tcpip.h>
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define DEFAULT_PORT "54321"
#define MAX_LINE 100
#define BUFFER_SIZE 1024 // 定义缓冲区大小为1024字节
int main()
{
// Initialize Winsock
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
printf("WSAStartup failed with error: %d\n", result);
return 1;
}
// Create a socket
SOCKET serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (serverSocket == INVALID_SOCKET) {
printf("Could not create socket: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Bind the socket to the address and port
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(atoi(DEFAULT_PORT));
if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
printf("Error binding socket.\n");
closesocket(serverSocket);
WSACleanup();
return 1;
}
printf("Server is listening on port %s...\n\n", DEFAULT_PORT);
// 循环接收文件
char buffer[BUFFER_SIZE];
SOCKADDR clientAddr;
int clientAddrLen = sizeof(clientAddr);
int bytesReceived;
int fileSize;
char fileNameAndExt[MAX_PATH * 4];
while (1)
{
// 取消超时设置,一直等待接收到 文件大小、文件名
DWORD timeout = 0; // 设置超时时间为0,表示取消超时设置。因为文件名和大小都还没接收到,没必要限制超时。文件本体才需要超时限制
setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
// 接收 文件大小、文件名
bytesReceived = recvfrom(
serverSocket, buffer, BUFFER_SIZE, 0,
&clientAddr, &clientAddrLen);
if (bytesReceived == SOCKET_ERROR) {
printf("Receive failed with error: %d\n", WSAGetLastError());
}
else {
// 取出文件大小(前4个字节),文件名
fileSize = (((unsigned char)buffer[0]) << 24) |
(((unsigned char)buffer[1]) << 16) |
(((unsigned char)buffer[2]) << 8) |
((unsigned char)buffer[3]);
strcpy(fileNameAndExt, buffer + 4);
printf("接收到文件:%s\n", fileNameAndExt);
printf("文件大小:%d\n", fileSize);
}
// 设置接收超时时间为0.5秒。接收文件本体需要设置超时参数,一旦超时,即认为文件发送完全/客户端断开
timeout = 500; // 0.5秒
setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
// 打开本地文件
FILE* pFile = fopen(fileNameAndExt, "wb");
if (pFile != NULL)
{
bool success = true;// 文件是否完全接收
int receivedSize = 0;// 已接收的字节数
while (1)
{
// Receive data from client
bytesReceived = recvfrom(
serverSocket, buffer, BUFFER_SIZE, 0,
&clientAddr, &clientAddrLen);
if (bytesReceived == SOCKET_ERROR) {
success = false;
int error = WSAGetLastError();
if (WSAGetLastError() == WSAETIMEDOUT) {
char clientIP[INET_ADDRSTRLEN];
int clientPort;
inet_ntop(AF_INET, &(((sockaddr_in*)&clientAddr)->sin_addr), clientIP, INET_ADDRSTRLEN);
clientPort = ntohs(((sockaddr_in*)&clientAddr)->sin_port);
printf("客户端 %s : %d 发来%s 文件过程中失去连接/接收超时.\n", clientIP, clientPort, fileNameAndExt);
break;
}
else {
printf("接收数据失败: %d\n", error);
break;
}
}
else
{
// 将缓冲区中的数据写入本地文件
if (fwrite(buffer, 1, bytesReceived, pFile) != bytesReceived)
{
printf("写入失败\n");
break;
}
// 接收到指定大小,即认为文件接收成功
receivedSize += bytesReceived;
if (receivedSize == fileSize)
{
printf("%s 接收成功!\n\n", fileNameAndExt);
break;
}
}
}
// 关闭本地文件
fclose(pFile);
// 文件未能接收完全,删除之
if (!success)
{
remove(fileNameAndExt);
printf("%s 已删除.\n\n", fileNameAndExt);
}
}
else
{
printf("无法打开本地文件\n\n");
}
}
closesocket(serverSocket);
WSACleanup();
system("pause");
return 0;
}
程序二Client:
#define _CRT_SECURE_NO_WARNINGS
#include <ws2tcpip.h>
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define DEFAULT_PORT "54321"
#define SERVER_IP "127.0.0.1" // 假设服务器在本地运行
#define BUFFER_SIZE 1024
class ChooseFile
{
private:
WCHAR name[MAX_PATH];
WCHAR ext[MAX_PATH];
char fileName_[MAX_PATH * 2];
char fileExt_[MAX_PATH * 2];
int fileSize;
public:
char fileName[MAX_PATH * 4];
char fileSizeAndName[MAX_PATH * 4 + 4];
HANDLE hFile;
int fileNameSize;
ChooseFile()
{
hFile = Choose(name, ext);
ConvertWCHARtoCHAR(name, fileName_, MAX_PATH * 2);
ConvertWCHARtoCHAR(ext, fileExt_, MAX_PATH * 2);
strPlusStr(fileName_, fileExt_, fileName);
fileNameSize = strlen(fileName);
// 将filesize添加到char数组的前面
unsigned bytes[4];
bytes[0] = (fileSize >> 24) & 0xFF;
bytes[1] = (fileSize >> 16) & 0xFF;
bytes[2] = (fileSize >> 8) & 0xFF;
bytes[3] = fileSize & 0xFF;
strcpy(fileSizeAndName + 4, fileName);
for (int i = 0; i < 4; i++)
{
fileSizeAndName[i] = bytes[i];
}
int temp = (bytes[0] << 24) |
(bytes[1] << 16) |
(bytes[2] << 8) |
bytes[3];
printf("文件名:%s\n", fileSizeAndName + 4);
printf("文件大小: %d\n", fileSize);
}
private:
void ConvertWCHARtoCHAR(const WCHAR* src, char* dest, int destSize) {
WideCharToMultiByte(CP_ACP, 0, src, -1, dest, destSize, NULL, NULL);
}
void strPlusStr(char* front, char* behind, char* dest)
{
// 计算合并后字符串的长度(包括结束符'\0')
int len1 = strlen(front);
int len2 = strlen(behind);
int total_len = len1 + len2 + 1; // 加1是为了结束符'\0'
// 将str1复制到merged_str
strcpy(dest, front);
// 将str2追加到merged_str的末尾
strcpy(dest + len1, behind);
}
HANDLE Choose(WCHAR* fileName, WCHAR* fileExt)
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL; // 或者设置为你的窗口句柄
ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0\0";// 设置了文件类型过滤器,允许用户选择文本文件或所有文件
ofn.nFilterIndex = 1;
ofn.lpstrFile = new WCHAR[MAX_PATH]; // 分配足够的空间存储文件路径
ZeroMemory(ofn.lpstrFile, MAX_PATH * sizeof(WCHAR)); // 确保缓冲区被清零
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = L"txt";// 设置了默认的文件扩展名为.txt
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn) == TRUE)
{
// 用户选择了文件,ofn.lpstrFile现在包含文件路径
printf("选择文件成功!\n");
// 提取文件名和扩展名
_wsplitpath_s(ofn.lpstrFile, NULL, 0, NULL, 0, fileName, MAX_PATH, fileExt, MAX_PATH);
// ... 接下来读取文件内容
HANDLE hFile = CreateFileW(
ofn.lpstrFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
fileSize = GetFileSize(hFile, NULL);
return hFile;
}
fileSize = 0;
return NULL;
}
}
};
int main()
{
char serverIP[16];
printf("请输入 服务器IP:\n");
scanf("%s", serverIP);
// Initialize Winsock
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
printf("WSAStartup failed with error: %d\n", result);
return 1;
}
// Create a socket
SOCKET clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (clientSocket == INVALID_SOCKET) {
printf("Error creating socket.\n");
WSACleanup();
return 1;
}
// Set up server address
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
int addrInfoSize = sizeof(serverAddr.sin_addr);
if (inet_pton(AF_INET, serverIP, &(serverAddr.sin_addr)) <= 0) {
printf("Invalid address/ Address not supported \n");
return 1;
}
serverAddr.sin_port = htons(atoi(DEFAULT_PORT));
// 选择 要发送的文件
ChooseFile file;// 构造函数中,就已经选定了文件
// 发送文件名
int bytesSent = sendto(
clientSocket, (char*)&file.fileSizeAndName, file.fileNameSize + 5, 0,
(struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (bytesSent == SOCKET_ERROR)
{
// 发送失败(文件名都发送失败了,还有什么好说的,直接结束程序)
printf("发送失败.\n");
closesocket(clientSocket);
WSACleanup();
system("pause");
return 0;
}
else
{
printf("正在发送%s\n", file.fileName);
}
// 循环读取文件内容到缓冲区 并 发送之
char buffer[BUFFER_SIZE];
DWORD dwBytesRead;
bool success = true;// 全部发送成功 标志
while (ReadFile(file.hFile, buffer, BUFFER_SIZE, &dwBytesRead, NULL) && dwBytesRead > 0)
{
// 处理缓冲区中的数据,比如发送到服务器
bytesSent = sendto(
clientSocket, buffer, dwBytesRead, 0,
(struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (bytesSent == SOCKET_ERROR)
{
success = false;
printf("Error sending data.\n");
break;
}
}
if (success)
printf("文件发送成功\n\n");
// Close the socket
closesocket(clientSocket);
WSACleanup();
system("pause");
return 0;
}
结语:
以上,计算机网络课程实验。
实验会在实验课当堂验收,本人第一次提前一天完成,当堂验收成功,发文以记之。