c - 如何在客户端-服务器应用程序中正确发送文件?
问题描述
当客户端可以注册、登录、向另一个客户端广播消息、发送文件等时,我想制作一个客户端-服务器应用程序。除了发送文件外,一切都很好。
在客户端应用程序中,我为要发送的每个文件创建了一个单独的线程。读取文件是成功的,但是发送不是很好。我应该在服务器项目中创建一个线程来接收客户端发送的字节吗?
我希望发送文件是异步的,以便在服务器接收文件时其他客户端可以与服务器通信。读取文件并向服务器发送数据的线程:
DWORD WINAPI SendFile(LPVOID param)
{
FileStruct* fileStruct = (FileStruct*)param;
CM_DATA_BUFFER* dataToSend = NULL;
CM_SIZE dataToSendSize = MAXLENGTH;
CM_ERROR error;
CM_SIZE sendBytesCount = 0;
FILE* f = fopen(fileStruct->filePath, "rb");
char buffer[2];
fseek(f, 0, SEEK_SET);
if (f == NULL)
{
perror((const char*)f);
}
char messageBuffer[10];
while (fread(buffer, 1, 1, f) == 1)
{
*(int*)messageBuffer = SENDTYPE;
messageBuffer[4] = buffer[0];
messageBuffer[5] = 0;
dataToSend = NULL;
error = CreateDataBuffer(&dataToSend, dataToSendSize);
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("Failed to create SEND data buffer with err-code=0x%X!\n"), error);
DestroyClient(fileStruct->client);
UninitCommunicationModule();
return (DWORD)-1;
}
error = CopyDataIntoBuffer(dataToSend, (const CM_BYTE*)messageBuffer, (CM_SIZE)strlen(messageBuffer));
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("CopyDataIntoBuffer failed with err-code=0x%X!\n"), error);
DestroyDataBuffer(dataToSend);
DestroyClient(fileStruct->client);
UninitCommunicationModule();
return (DWORD)-1;
}
error = SendDataToServer(fileStruct->client, dataToSend, &sendBytesCount);
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("SendDataToServer failed with err-code=0x%X!\n"), error);
DestroyDataBuffer(dataToSend);
DestroyClient(fileStruct->client);
UninitCommunicationModule();
return (DWORD)-1;
}
DestroyDataBuffer(dataToSend);
}
return (DWORD)0;
}
这是 Thread Server 负责接收数据的部分代码:
while ((error = ReceiveDataFromClient(newClient, receivedData, &numberOfBytesRead)) == 0)
{
message = (char*)receivedData->DataBuffer;
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("ReceiveDataFormServer failed with err-code=0x%X!\n"), error);
DestroyDataBuffer(sendData);
DestroyDataBuffer(receivedData);
break;
}
type = *(int*)receivedData->DataBuffer;
printf("%x\n", type);
if (type == SENDTYPE)
{
printf("%c", (char)receivedData->DataBuffer[4]);
DestroyDataBuffer(receivedData);
receivedData = NULL;
error = CreateDataBuffer(&receivedData, MAXLENGTH);
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("Creating receivedDataBuffer failed with err-code =0x%X!\n"), error);
UninitCommunicationModule();
}
continue;
}
这是 ReceiveDataFromClient 函数:
CM_ERROR ReceiveDataFromClient(CM_SERVER_CLIENT* Client, CM_DATA_BUFFER* DataBufferToReceive, CM_SIZE* SuccessfullyReceivedBytesCount)
{
if (Client == NULL || DataBufferToReceive == NULL || SuccessfullyReceivedBytesCount == NULL)
return CM_INVALID_PARAMETER;
CM_ERROR error = ReceiveData(
Client->ClientConnection
, DataBufferToReceive->DataBuffer
, DataBufferToReceive->DataBufferSize
, SuccessfullyReceivedBytesCount
);
if (CM_IS_ERROR(error))
return error;
DataBufferToReceive->UsedBufferSize = *SuccessfullyReceivedBytesCount;
return error;
}
这是 ReceiveData 函数:
CM_ERROR ReceiveData(CM_CONNECTION* Connection, CM_BYTE* OutputDataBuffer, CM_SIZE OutputDataBufferSize, CM_SIZE* SuccessfullyReceivedBytesCount)
{
if (Connection == NULL)
return CM_INVALID_CONNECTION;
if (INVALID_SOCKET == Connection->ConnectionSocket)
return CM_INVALID_PARAMETER;
int receiveResult = recv(Connection->ConnectionSocket, (char*) OutputDataBuffer, OutputDataBufferSize, 0);
if (receiveResult == SOCKET_ERROR)
{
CM_LOG_ERROR(TEXT("recv failed with err-code=0x%X!"), WSAGetLastError());
return CM_CONNECTION_RECEIVE_FAILED;
}
if (receiveResult == 0)
return CM_CONNECTION_TERMINATED;
*SuccessfullyReceivedBytesCount = (CM_SIZE)receiveResult;
return CM_SUCCESS;
}
解决方案
推荐阅读
- java - 查询字符串 sql
- r - NBA 四分之一秒剩余秒数转换为比赛剩余秒数
- python - Python数据表(或熊猫):基于两列的数据帧的棘手排序
- java - 带有 SpinnerNumberModel 的 JSpinner:是否验证输入的数字?
- c# - Blazor WebAssembly - 找不到适合类型“JwtSecurityTokenHandler”的构造函数
- c# - C# 帮助在更新前验证表数据
- sharepoint-online - 在流程中使用“发送 Http 操作”更新人员组字段时出错
- node.js - Nodejs:Twitter Image Bot 上的 ENOENT
- c - 在 C 中使用命名管道读取和写入同一个文件
- python - 安装 PyAudio