提问人:Msain 提问时间:9/4/2022 更新时间:9/6/2022 访问量:258
read() 和 write() 函数在 C 上的本地连接(同一台计算机)上的 TCP 连接期间返回 -1
read() and write() functions return -1 during a TCP connection on local connection (same computer) on C
问:
我编写了一个代码,用于将文件内容从客户端传输到服务器。这意味着我们在服务器端更新某个文件。此过程根据用户输入每 N 秒继续一次。但是,我遇到了一个错误,即:
即使在本地连接(同一台计算机)上,write() 和 read() 函数在文件传输过程中也会返回 -1。这个问题甚至可能不会不时表现出来。但是,当用户传输较大的文件(超过 30MB)时,它更有可能显现出来。因此,这个问题肯定在那里等待某些东西来触发它,这对于任何程序来说都是一个非常不方便的方面。奇怪的是,如果我使用 sleep() 函数,例如等待 1 秒钟,然后在套接字上 write()/read(),则不会发生此问题。请解释为什么会发生这种情况以及我该如何补救。 此外,在所有其他代码中,我所看到的只是 exit(0),如果 read() 或 write() 在连接期间返回 -1。 感谢您的指导
不幸的是,在类似的问题中,我找不到任何解决方案。如果您能解释为什么会出现此类问题以及我如何解决它,我将不胜感激。为了您的方便,我在下面解释了完整的过程。
- 此代码背后的主要思想是从定期更新的文件中传输数据。因此,我们应该每 N 秒向服务器发送一次剩余数据。
- 服务器(接收方)和客户端(发送方)相互连接(对于像您这样的专业用户来说并不是什么新鲜事)。
- 服务器(接收器)发送持久化的数据量,用户计算剩余的数据量。完成此步骤后,服务器和客户端都知道在当前迭代中应传输多少数据。
- client 将所有剩余数据读取到 cacheBuffer 并关闭该文件。(我应该说 cacheBuffer 等于剩余的字节,并且在客户端和服务器中都有效)
- 在 main(内部)while 循环中,我们从 cacheBuffer 复制到 mssg 结构,然后通过套接字发送该结构。
- 同样,客户端内部的 while 循环读取结构 mssg 并将数据复制到其缓存缓冲区。
- 最后,当发送/接收结束时,接收方(服务器)将缓存缓冲区内容写入目标文件,该过程将继续。
客户端代码
/*
How to compile ->
(1) make all
if no make was provided then gcc server.c utilityFunctionsMHZ.h -o server
(2) ./server FILENAME PORT_NUMBER SLEEP_TIMER MAX_BUFFER_SIZE
Example: ./server mainFile2.log 5500 10 4096
(3) ./client FILENAME SERVER_ADDR PORT_NUMBER
Example: ./client mainFile.log 172.17.34.89 5500
*/
#include "utilityFunctionsMHZ.h"
int main (int argc, char* argv[])
{
// Initial Error Check And Call Initializer
if (argc < 4)
{
fprintfSwitchable(NULL, 0, "[+client] Please use the given format: ./client FILENAME SERVER_ADDR PORT_NUMBER\n");
exit(0);
}
else if (!isFileAvailable(argv[1], "client", NULL))
{
exit(0);
}
else
{
Initializer ("client", NULL);
fprintfSwitchable(NULL, 0, "[+%s] Make Sure to Run server First.\n", "client");
}
// Input Parameters
const char* fileLocFull = argv[1];
char* serverIP = argv[2];
int portNumber = atoi(argv[3]);
// Buffer & Cache Properties and Size
struct bufferTCP* mssg = CreateBufferTCP();
size_t MAX_CACHE_SIZE, CACHE_SIZE;
char* cacheBuffer;
// File Process, Data Structure (NACK-Sender & ACK-Reciever)
FILE* filePtr_NACK;
size_t fileMemory_NACK = 0;
size_t fileMemory_ACK = 0;
size_t fileRemainMemory = 0;
// Create Socket via TCP Protocol & Error Check
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
fprintfSwitchable(NULL, 1, "[-client] Error in Socket Initiation!\n");
else
fprintfSwitchable(NULL, 0, "[+client] Socket Successfully Initiated.\n");
// Socket main Structures
struct sockaddr_in* serverAddr = malloc(sizeof(struct sockaddr_in));
// Socket Structures Memory Allocation Test
if (serverAddr == NULL)
fprintfSwitchable(NULL, 1, "[-client] Memory Allocation for sockadd_in strctures Failed!\n");
else
fprintfSwitchable(NULL, 0, "[+client] Memory Allocation for sockadd_in strctures Successfully Completed.\n");
// Set-up server parameters
bzero(serverAddr, sizeof(struct sockaddr_in)); //memset(serverAddr, 0x00, sizeof(struct sockaddr_in));
serverAddr->sin_family = AF_INET;
//serverAddr->sin_addr.s_addr = inet_addr(serverIP);
inet_pton(AF_INET, serverIP, &(serverAddr->sin_addr));
serverAddr->sin_port = htons(portNumber);
// Connection Request to Server
if (connect(sockfd, (struct sockaddr*) serverAddr, sizeof(struct sockaddr_in)) == -1)
fprintfSwitchable(NULL, 1, "[-client] Error in Connecting to Server!\n");
else
fprintfSwitchable(NULL, 0, "[+client] Connection Successfully Accepted.\n");
if (read(sockfd, &MAX_CACHE_SIZE, sizeof(size_t)) == -1)
fprintfSwitchable(NULL, 1, "[-client] Error in MAX CACHE Size Negitiation!\n");
else
fprintfSwitchable(NULL, 0, "[+client] CACHE Size is Set Equal to Server: %lu.\n", MAX_CACHE_SIZE);
// Initializing Sender Sleep Clock
size_t sleepTimer;
if (read(sockfd, &sleepTimer, sizeof(size_t)) == -1)
fprintfSwitchable(NULL, 1, "[-client] Error in Sleep Timer Negitiation!\n", 1, 1);
else
fprintfSwitchable(NULL, 0, "[+client] Sleep Timer is Set Equal to Server: %lu\n", sleepTimer);
int iack;
int ACKFLAG = 0;
size_t OveralIteration = 0;
size_t SentBytes;
size_t Not_Written = 0;
ssize_t readFLAG;
ssize_t writeFLAG;
size_t InnerIteration = 0;
fprintfSwitchable(NULL, 0, "**********************Client-Side::Sending Started**************************\n");
while (1)
{
fileMemory_NACK = FileSizeCalculator(fileLocFull);
// File Status @ Server (Reciever)
if (read(sockfd, &fileMemory_ACK, sizeof(size_t)) == -1)
fprintfSwitchable(NULL, 1, "[-client] Error in reading File Info!\n");
else
fprintfSwitchable(NULL, 0, "[+client] File (Size) Info is Recieved Successfully.\n");
// Send-Recieve Validity
fileRemainMemory = fileMemory_NACK - fileMemory_ACK;
// Send Expecting Data Size For Server
if (write(sockfd, &fileRemainMemory, sizeof(size_t)) == -1)
fprintfSwitchable(NULL, 1, "[-client] Failed To Send Remaining Memory Info!\n");
else
fprintfSwitchable(NULL, 0, "[+client] Session [%lu] Overview: \nACK Memory is %lu\nNACK Memory is %lu\nRemaining Memory is: %lu\n\n",
OveralIteration, fileMemory_ACK, fileMemory_NACK, fileRemainMemory);
// Assess Sending
if (fileMemory_NACK == fileMemory_ACK)
{
fprintfSwitchable(NULL, 0, "[+client] Remaining Memory is Zero. Send Process Will Contine After %lu[s] Timeout.\n", sleepTimer);;
continue;
}
else if (fileRemainMemory < BUFFER_MAX)
{
fprintfSwitchable(NULL, 0, "[+client] Remaining Buffer is Smaller Than Cache Limit %lu. Send Process Will Contine After %lu[s] Timeout.\n",
BUFFER_MAX, sleepTimer);
Not_Written++;
if (Not_Written < 10)
continue;
else
Not_Written = 0;
}
// Creating Cache
CACHE_SIZE = fileRemainMemory;
cacheBuffer = (char*) calloc (CACHE_SIZE, sizeof(char));
bzero(cacheBuffer, CACHE_SIZE);
// Copy Data From File to CACHE-Buffer
filePtr_NACK = fopen(fileLocFull, "r");
fseek(filePtr_NACK, fileMemory_ACK, SEEK_SET);
fread(cacheBuffer, sizeof(char), CACHE_SIZE, filePtr_NACK);
fclose(filePtr_NACK);
ACKFLAG = 0;
SentBytes = 0;
fileRemainMemory = CACHE_SIZE;
InnerIteration = 0;
while (1)
{
// EXIT CONDITION
if (fileRemainMemory == 0) break;
// Evaluate Buffer Size
if (fileRemainMemory >= BUFFER_MAX)
mssg->BUFFER_USED = BUFFER_MAX;
else
mssg->BUFFER_USED = fileRemainMemory;
// Copy From CACHE to Socket Buffer and Send
memcpy(mssg->mssgPtr, cacheBuffer+SentBytes, mssg->BUFFER_USED);
writeFLAG = write(sockfd, mssg, sizeof(struct bufferTCP));
fprintfSwitchable(NULL, 0, "[+client] Iter %ld :: %ld/%ld Sent!\n", InnerIteration++, writeFLAG, sizeof(struct bufferTCP));
// Cases:
if (writeFLAG == -1)
{
// Display Problem
fprintfSwitchable(NULL, 0, "[-client] Error While Sending Buffer!\n");
fprintfSwitchable(NULL, 0, "[-client] %s\n", strerror(errno));
}
else if (writeFLAG < sizeof(struct bufferTCP))
{
// Display Problem
fprintfSwitchable(NULL, 0, "[-client] Only %ld/%ld Sent!\n", writeFLAG, sizeof(struct bufferTCP));
}
else
{
// In Session Statistics
fileRemainMemory -= mssg->BUFFER_USED;
SentBytes += mssg->BUFFER_USED;
fprintfSwitchable(NULL, 0, "[+client] (%lu) Current-Iteration | (%lu) Total-Sent | (%lu) Remaining.\n", writeFLAG, SentBytes, fileRemainMemory);
}
bzero(mssg->mssgPtr, BUFFER_MAX);
}
if (writeFLAG != -1 && fileRemainMemory == 0)
{
fileMemory_ACK = SentBytes;
OveralIteration++;
}
// Session Summary
fprintfSwitchable(NULL, 0, "[+client] Session %lu Summary:\nACK Memory is %lu :: Remaining Memory is: %lu\n\n",
OveralIteration, fileMemory_ACK, fileRemainMemory);
free(cacheBuffer);
// Exit Condition
if (isEnd (sleepTimer, "client")) break;
}
fprintfSwitchable(NULL, 0, "\n***********************Client-Side::Sending Ended***************************\n");
close(sockfd);
free(serverAddr);
free(mssg);
return 0;
}
服务器代码:
/*
How to compile ->
(1) make all
if no make was provided then gcc server.c utilityFunctionsMHZ.h -o server
(2) ./server FILENAME PORT_NUMBER SLEEP_TIMER CHACHE_SIZE_MAX
Example: ./server mainFile2.log 5500 10 4096
(3) ./client FILENAME SERVER_ADDR PORT_NUMBER
Example: ./client mainFile.log 172.17.34.89 5500
*/
#include "utilityFunctionsMHZ.h"
int main (int argc, char* argv[])
{
// Initial Error Check And Call Initializer
if (argc < 5)
{
fprintfSwitchable(NULL, 0, "[+server] Please use the following format to initiate the ./server FILENAME PORT_NUMBER SLEEP_TIMER MAX_CACHE_SIZER\n");
exit(0);
}
else
{
Initializer ("server", NULL);
}
// Input Parameters
const char* fileLocFull = argv[1];
int portNumber = atoi(argv[2]);
size_t sleepTimer = atoi(argv[3]);
size_t MAX_CACHE_SIZE = atoi(argv[4]);
size_t WaitQueue = 5;
// server :: Socket Accept Client Request
socklen_t socklen = sizeof(struct sockaddr_in);
// File Process, Data Structure (NACK is the Sender/Client Side)
if (!isFileAvailable(argv[1], "server", NULL))
{
FILE* filePtr_ACK = fopen(fileLocFull, "w");
fclose(filePtr_ACK);
}
//size_t checker = FileCorrector (fileLocFull);
size_t checker = FileModifier (fileLocFull);
// File Process, Data Structure (NACK-Sender & ACK-Reciever)
FILE* filePtr_ACK;
size_t fileMemory_ACK = 0;
size_t fileRemainMemory = 0;
// Buffer Properties and Size (Set Sender/Client Buffer-Size Equal to Server)
struct bufferTCP* mssg = CreateBufferTCP();
// Cache properties
size_t CACHE_SIZE;
char* cacheBuffer;
// socket End-Point
int sockfd, sockfd_new;
// client :: Initiation Socket via TCP Protocol & Error Check
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
fprintfSwitchable(NULL, 1, "[-server] Error in Socket Initiation!\n");
else
fprintfSwitchable(NULL, 0, "[+server] Socket Successfully Initiated.\n");
// Socket main Structures
struct sockaddr_in* serverAddr;
struct sockaddr_in* clientAddr;
serverAddr = malloc(sizeof(struct sockaddr_in));
clientAddr = malloc(sizeof(struct sockaddr_in));
// Socket Structures Memory Allocation Test
if (clientAddr == NULL || serverAddr == NULL)
fprintfSwitchable(NULL, 1, "[-server] Memory Allocation for sockadd_in strctures Failed!\n");
else
fprintfSwitchable(NULL, 0, "[+server] Memory Allocation Successfully Completed.\n");
bzero(serverAddr, sizeof(struct sockaddr_in)); //memset(serverAddr, 0x00, sizeof(struct sockaddr_in));
bzero(clientAddr, sizeof(struct sockaddr_in)); //memset(clientAddr, 0x00, sizeof(struct sockaddr_in));
// set-up Server parameters
serverAddr->sin_family = AF_INET;
serverAddr->sin_addr.s_addr = INADDR_ANY; // inet_addr(clientIP);
serverAddr->sin_port = htons(portNumber);
// server :: Socket Binding
if (bind(sockfd, (struct sockaddr*) serverAddr, sizeof(struct sockaddr_in)) == -1)
fprintfSwitchable(NULL, 1, "[-server] Error in Socket Binding!\n");
else
fprintfSwitchable(NULL, 0, "[+server] Socket Successfully Binded.\n");
// server :: Socket Listening
if (listen(sockfd, WaitQueue) == -1)
fprintfSwitchable(NULL, 1, "[-server] Error while Listening!\n");
else
fprintfSwitchable(NULL, 0, "[+server] Listening...\n");
// server :: Socket Listening
sockfd_new = accept(sockfd, (struct sockaddr*) clientAddr, &socklen);
if (sockfd_new == -1)
fprintfSwitchable(NULL, 1, "[-server] Error in Accepting Client Connection!\n");
else
fprintfSwitchable(NULL, 0, "[+server] Connection Successfully Accepted.\n");
// Establishing BUFFER_MAX_SIZE (Set Sender/Client Buffer-Size Equal to Server)
if (write(sockfd_new, &MAX_CACHE_SIZE, sizeof(size_t)) == -1)
fprintfSwitchable(NULL, 1, "[-server] Error in Buffer Size Negitiation!\n");
else
fprintfSwitchable(NULL, 0, "[+server] MAX Buffer-Size is Sent to client: %lu.\n", MAX_CACHE_SIZE);
// Initializing Sender Sleep Clock (Set Sender/Client Buffer-Size Equal to Server)
if (write(sockfd_new, &sleepTimer, sizeof(size_t)) == -1)
fprintfSwitchable(NULL, 1, "[-server] Error in Sleep Timer Negitiation!\n");
else
fprintfSwitchable(NULL, 0, "[+server] Sleep-Timer is Sent to client: %lu\n", sleepTimer);
int ACKFLAG = 0, CONFLAG = 0;
size_t OveralIteration = 0;
size_t SentBytes;
size_t Not_Written;
int iack = 0;
ssize_t readFLAG;
ssize_t writeFLAG;
size_t InnerIteration = 0;
fprintfSwitchable(NULL, 0, "**********************Server-Side::Recieving Started**************************\n");
while (1)
{
// File Status @ Server (Reciever)
fileMemory_ACK = FileSizeCalculator(fileLocFull);
// Send ACK Status
if (write(sockfd_new, &fileMemory_ACK, sizeof(size_t)) == -1)
fprintfSwitchable(NULL, 1, "[-server] Error in Sending File Info!\n");
else
fprintfSwitchable(NULL, 0, "[+server] File (Size) Info Sent Successfully.\n");
// Recieve Expecting Data Size From Client
if (read(sockfd_new, &fileRemainMemory, sizeof(size_t)) == -1)
fprintfSwitchable(NULL, 1, "[-server] Failed to Recieve Remaining Memory Info!\n");
else
fprintfSwitchable(NULL, 0, "[+server] Session [%lu] Overview:\nACK Memory is: %lu\nRemaining Memory is: %lu\n\n",
OveralIteration, fileMemory_ACK, fileRemainMemory);
if (fileRemainMemory == 0)
{
fprintfSwitchable(NULL, 0, "[+server] Remaining Memory is Zero. Process Will Contine After %lu[s] Timeout.\n", sleepTimer);
continue;
}
else if (fileRemainMemory < BUFFER_MAX)
{
fprintfSwitchable(NULL, 0, "[+server] Remaining Buffer is Smaller Than Cache Limit %lu. Recieve Process Will Contine After %lu[s] Timeout.\n",
BUFFER_MAX, sleepTimer);
Not_Written++;
if (Not_Written < 10)
continue;
else
Not_Written = 0;
}
// Creating Cache
CACHE_SIZE = fileRemainMemory;
cacheBuffer = calloc (CACHE_SIZE, sizeof(char));
bzero(cacheBuffer, CACHE_SIZE);
ACKFLAG = 0;
SentBytes = 0;
fileRemainMemory = CACHE_SIZE;
InnerIteration = 0;
while (1)
{
// EXIT CONDITION
if (fileRemainMemory == 0) break;
// Recieve Buffer
readFLAG = read(sockfd_new, mssg, sizeof(struct bufferTCP));
fprintfSwitchable(NULL, 0, "[+server] Iter %ld :: %ld/%ld Sent!\n", InnerIteration++, readFLAG, sizeof(struct bufferTCP));
// Cases:
if (readFLAG == -1)
{
// Display Problem
fprintfSwitchable(NULL, 0, "[-server] Error While Reading Buffer Size!\n");
}
else if (readFLAG < sizeof(struct bufferTCP))
{
// Copy From CACHE to Socket Buffer
fprintfSwitchable(NULL, 0, "[-server] Only %ld/%ld Recieved!\n",readFLAG, sizeof(struct bufferTCP));
fprintfSwitchable(NULL, 0, "[-server] %s\n", strerror(errno));
}
else
{
// Copy From CACHE to Socket Buffer
memcpy(cacheBuffer+SentBytes, mssg->mssgPtr, mssg->BUFFER_USED);
// In Session Statistics
fileRemainMemory -= mssg->BUFFER_USED;
SentBytes += mssg->BUFFER_USED;
fprintfSwitchable(NULL, 0, "[+server] (%lu) Current-Iteration | (%lu) Total-Sent | (%lu) Remaining.\n", readFLAG, SentBytes, fileRemainMemory);
}
bzero(mssg->mssgPtr, BUFFER_MAX);
}
if (readFLAG != -1 && fileRemainMemory == 0)
{
fileMemory_ACK = SentBytes;
// Copy Data From File to CACHE-Buffer
filePtr_ACK = fopen(fileLocFull, "a");
fwrite(cacheBuffer, sizeof(char), CACHE_SIZE, filePtr_ACK);
fclose(filePtr_ACK);
OveralIteration++;
}
// Session Summary-alIteration, fileMemory_ACK, fileRemainMemory);
free(cacheBuffer);
// Exit Condition
if (isEnd (sleepTimer, "server")) break;
}
fprintfSwitchable(NULL, 0, "\n***********************Server-Side::Recieving Ended***************************\n");
close(sockfd);
close(sockfd_new);
free(serverAddr);
free(clientAddr);
free(mssg);
return 0;
}
使用的库
#ifndef utilityFunctionsMHZ_H
#define utilityFunctionsMHZ_H
#include <stdio.h> //:: standard IO c-functions
#include <string.h> //:: standard c-string functions
#include <unistd.h> //:: standard POSIX operating system API (read/write/send/recv)
#include <stdlib.h> //:: standard ALLOC c-functions (malloc, atoi)
#include <sys/types.h> //:: definitions of data types used in sys/socket & netinet/in
#include <sys/socket.h> //:: definitions of structures needed for internet domain such as (struct sockaddr)
#include <netinet/in.h> //:: definitions of (struct sockaddr_in)
#include <netdb.h> //:: definitions of (struct hostnet) to store info of a given host & IPV-4
#include <arpa/inet.h> //:: inet()
#include <sys/stat.h>
#include <stdarg.h> //:: Variable Input function
#include <errno.h>
#define BUFFER_MAX 1024
struct bufferTCP
{
char mssgPtr[BUFFER_MAX];
size_t BUFFER_USED;
};
// Usefull functions
struct bufferTCP* CreateBufferTCP();
void WriteLog(const char* logFileName, const char* mssg);
size_t FileCorrector (const char* fileName);;
FILE* FileOpenSafe (const char* fileName, const char* rwaMode);
size_t FileSizeCalculator (const char* fileName);
void fprintfSwitchable(FILE* stream, int errFlag, const char* mssg, ...);
FILE* FileOpenSafe (const char* fileName, const char* rwaMode);
size_t FileSizeCalculator (const char* fileName);
size_t FileCorrector (const char* fileName);
size_t FileModifier(const char* fileName);
void Initializer (const char* caller, FILE* stream);
int isEnd (size_t sleepTimer, const char* caller);
int isFileAvailable (const char* fileLocFull, const char* caller, FILE* stream);
void WriteLog(const char* logFileName, const char* mssg)
{
FILE* logFilePtr = fopen(logFileName, "a");
//fputs(mssg, logFilePtr);
fclose(logFilePtr);
}
void fprintfSwitchable(FILE* stream, int errFlag, const char* mssg, ...)
{
va_list args;
va_start(args, mssg);
if (stream == NULL)
{
vfprintf(stdout, mssg, args);
fflush(stdout);
}
else
{
vfprintf(stream, mssg, args);
fflush(stream);
}
if (errFlag) exit(1);
va_end(args);
}
FILE* FileOpenSafe (const char* fileName, const char* rwaMode)
{
if (fileName == NULL)
fprintfSwitchable(NULL, -1, "FileName or Location is Incorrect!\n");
FILE* filePtr = fopen(fileName, rwaMode);
if (filePtr == NULL)
fprintfSwitchable(NULL, -1, "File Location is Invalid Or File Does Not Exists!\n");
return filePtr;
}
size_t FileSizeCalculator (const char* fileName)
{
FILE* filePtr = FileOpenSafe(fileName, "r");
int fileDescriptor = fileno(filePtr);
struct stat fileInfo;
bzero(&fileInfo, sizeof(struct stat));
fstat(fileDescriptor, &fileInfo);
size_t fileSize = fileInfo.st_size;
fclose(filePtr);
return fileSize;
}
size_t FileCorrector (const char* fileName)
{
size_t fileSize = FileSizeCalculator (fileName);
size_t fileSizeTrue;
if (fileSize == 0)
{
fprintfSwitchable(NULL, 0, "File is Empty, thus requires no correction!\n");
return 0;
}
// Main & Temp File
FILE* mainFile = FileOpenSafe (fileName, "r");
FILE* tempFile = FileOpenSafe("temp", "w");
// Fault Detection (\00 0\0 00) and correct
char checkBuff[3];
char curserrChar;
size_t ii;
for (ii = 0; ii < fileSize; ii++)
{
curserrChar = fgetc(mainFile);
//printf("%c", curserrChar);
if (curserrChar == '\00')
{
fileSizeTrue = ftell(mainFile)-2;
break;
}
fputc(curserrChar, tempFile);
}
fclose(mainFile);
fclose(tempFile);
// Remove The Old File
if (remove(fileName) == 0)
fprintfSwitchable(NULL, 0, "Faulty File (%s) Removed Successfully.\n", fileName);
else
fprintfSwitchable(NULL, 1, "Error while Removing the Faulty File: %s!\n", fileName);
// Remove The Old File
if (rename("temp", fileName) == 0)
fprintfSwitchable(NULL, 0, "Corrected File Renamed Successfully.\n");
else
fprintfSwitchable(NULL, 1, "Error while Removing the Faulty File: %s!\n");
fprintfSwitchable(NULL, 0, "Correction Implemented Successfully.\n");
return fileSizeTrue;
}
size_t FileModifier(const char* fileName)
{
size_t fileSize = FileSizeCalculator (fileName);
size_t fileSizeTrue;
if (fileSize == 0)
{
fprintfSwitchable(NULL, 0, "[+server] File is Empty, thus requires no correction.\n");
return 0;
}
// Main & Temp File
FILE* mainFile = FileOpenSafe (fileName, "r");
FILE* tempFile = FileOpenSafe("temp", "w");
// Fault Detection (\00 0\0 00) and correct
char checkBuff[3];
char curserrChar;
size_t ii;
for (ii = 0; ii < fileSize; ii++)
{
curserrChar = fgetc(mainFile);
if (curserrChar == '\00') break;
fputc(curserrChar, tempFile);
}
fclose(mainFile);
fclose(tempFile);
mainFile = FileOpenSafe (fileName, "w");
tempFile = FileOpenSafe("temp", "r");
fileSizeTrue = FileSizeCalculator ("temp");
ii=0;
for (ii = 0; ii < fileSizeTrue; ii++)
{
curserrChar = fgetc(tempFile);
fputc(curserrChar, mainFile);
}
fclose(mainFile);
fclose(tempFile);
// Remove The Old File
if (remove("temp") == 0)
fprintfSwitchable(NULL, 0, "[+server] Temp File Removed Successfully.\n");
else
fprintfSwitchable(NULL, 1, "[-server] Error while Removing the Faulty File!\n");
fprintfSwitchable(NULL, 0, "[+server] File Modifier Executed Successfully.\n");
return fileSizeTrue;
}
void Initializer (const char* caller, FILE* stream)
{
// Initial confirmation client side
char checkSend;
fprintfSwitchable(stream, 0, "[+%s] Start Process [Y/N]: ", caller);
scanf(" %c", &checkSend);
if (checkSend == 'N' || checkSend == 'n')
{
fprintfSwitchable(stream, 0, "[-%s] Abort Process As Requested!\n", caller);
exit(0);
}
else
return;
}
int isEnd (size_t sleepTimer, const char* caller)
{
// Exit Material
fd_set s;
struct timeval timeout;
char exitFlag[12];
memset(&exitFlag, 'F', 12);
int sFlag;
fflush(stdout);
FD_ZERO(&s);
FD_SET(0, &s);
timeout.tv_sec = sleepTimer; timeout.tv_usec = 0;
sFlag = select(1, &s, NULL, NULL, &timeout);
if (sFlag < 0)
return 0;
else if (sFlag == 0)
{
fflush(stdout);
fprintfSwitchable(NULL, 0, "-\n");
return 0;
}
else
{
fgets(exitFlag, 12, stdin);
fprintfSwitchable(NULL, 0, "[+%s] To Quit, please enter \"exit\": ", caller);
fflush(stdout);
if ( memcmp(&exitFlag, "exit", 4) == 0 )
return 1;
else
return 0;
}
}
int isFileAvailable (const char* fileLocFull, const char* caller, FILE* stream)
{
// Checks if The Target Send File Exists!
FILE* filePtr_NACK = fopen(fileLocFull, "r");
if (filePtr_NACK == NULL)
{
fprintfSwitchable(stream, 0, "[-%s] Not Such File Name Exists!\n", caller);
return 0;
}
else
{
fprintfSwitchable(stream, 0, "[+%s] File Found Successfully.\n", caller);
fclose(filePtr_NACK);
return 1;
}
}
void copyWithOffsetDest(char* dest, const char* src, size_t start, size_t length)
{
size_t i = 0;
for (i = 0; i < length; i++)
dest[start+i] = src[i];
}
void copyWithOffsetSource(char* dest, const char* src, size_t start, size_t length)
{
size_t i = 0;
for (i = 0; i < length; i++)
dest[i] = src[i+start];
}
struct bufferTCP* CreateBufferTCP()
{
struct bufferTCP* mssg = (struct bufferTCP*)
malloc(sizeof(struct bufferTCP));
return mssg;
}
#endif
生成文件
all: client server
ftpclient: client.c
gcc -std=gnu99 -Wall $< -o $@
ftpserver: server.c
gcc -std=gnu99 -Wall $< -o $@
clean:
rm -f client server *.o *~ core
rm server client
答:
我已经找到了问题的答案。 正如 @user207421 和 @Martin James 所建议的那样(谢谢你们俩),问题出在 write() read() IO 上。我还不明白它是如何导致分割的,但教训是 read() 和 write() 函数需要循环来发送和接收数据,正如我们预期的那样。否则,他们会做其他事情,我们不能简单地预测它。在下面,我附加了我如何修复代码。我希望它能使其他人免于犯同样的错误。
服务器环路
readFLAG = 0;
bzero(mssg->mssgPtr, BUFFER_MAX);
while ( (readFLAG = read(sockfd_new, (mssg->mssgPtr)+readFLAG, BUFFER_MAX-readFLAG)) != BUFFER_MAX )
{
if (readFLAG == 0 || mssg->mssgPtr[readFLAG] == '\0')
break;
}
mssg->BUFFER_USED = readFLAG;
客户端循环
bzero(mssg->mssgPtr, BUFFER_MAX);
memcpy(mssg->mssgPtr, cacheBuffer+SentBytes, mssg->BUFFER_USED);
while ( (writeFLAG = write(sockfd, mssg->mssgPtr, mssg->BUFFER_USED)) != mssg->BUFFER_USED );
评论
read()
write()
评论
close()
shutdown()