我正在开发一个二进制文件传输程序,客户端必须将文件上传到服务器。对于这种情况,我需要先发送文件名,然后再发送文件内容。但这对我来说不可行。
让我们看看代码:
// Client-side code to send file name
void sendFileName(
int sd, /*Socket Descriptor*/
char *fname) /*Array Containing the file name */
{
int n , byteswritten=0 , written ;
char buffer[1024];
strcpy(buffer , fname);
n=strlen(buffer);
while (byteswritten<n)
{
written=write(sd , buffer+byteswritten,(n-byteswritten));
byteswritten+=written;
}
printf("File name : %s sent to server \n",buffer);
}
在这段代码中,我将文件名写在socket&amp; amp; server将从socket读取名称,如下所示:
// Server-side code to read file name from client
while ((n = read((int)connfd, (fname + pointer), 1024)) > 0)
{
pointer=pointer+n;
}
嗯,问题是我必须在发送文件名之后关闭客户端的写端,这将是服务器端代码的FIN段,以便停止从服务器读取。
如果我关闭读取结束,如:
shutdown(sd,SHUT_WR); //Closing write end at client side
如何通过套接字将文件内容写入(即发送)到服务器,以便它可以从套接字读取?
注意:我所做的是在文件名中添加来自客户端的文件内容,并在内容中添加一个特殊字符(为了通知文件名末尾),然后添加文件内容。
在客户端,
void readWriteFile(
int sd, /*Socket Descriptor */
int fd, /*File Descriptot */
char *fname) /*File Name */
{
char buffer[1050];
int n;
int len = 0;
char *tmp = (char *)malloc(sizeof (char) * (strlen(fname) + 2));
strcpy(tmp, fname); //Copying the file name with tmp
strcat(tmp, "/"); //Appending '/' to tmp
len = strlen(tmp);
memset(buffer, '\0', sizeof (buffer));
strcpy(buffer, tmp); //Now copying the tmp value to buffer
while ((n = read(fd, buffer + len, 1024)) > 0)
{
if (write(sd, buffer, n) != n)
{
printf("File write Error \n");
exit(0);
}
len = 0;
}
printf("File sent successfully \n");
}
在服务器端,
char fname[50], buffer[1024];
int n, fd;
int i;
int start = 0;
while ((n = read((int)connfd, buffer, 1024)) > 0) // Reading from socket
{
if (!start)
{
/* This 'if' loop will executed almost once i.e. until
getting the file name */
for (i = 0; i < 1024; i++)
{
/* Since '/' is the termination character for file name */
if (buffer[i] == '/')
{
start = 1; // Got the file name
break;
}
fname[i] = buffer[i]; //Storing the file name in fname
}
fname[i] = '\0';
/* Creating the file in the server side */
fd = open(fname, O_WRONLY | O_CREAT, S_IRWXU);
if (fd < 0)
{
perror("File error");
exit(0);
}
/* Here writing the buffer content to the file after
the (buffer+i+1), because after this address only, we
can get the original file content */
write(fd, buffer + i + 1, n);
}
else
{
write(fd, buffer, n);
}
}
printf("%s received successful \n", fname);
此代码适用于图像,可执行文件和文本文件。但是,如果我发送任何音频文件,它不会在服务器端播放。尺寸仍然是大小。但我想知道为什么这会发生在音频文件上。逻辑上有什么不对吗?我还没有尝试过视频文件。
答案 0 :(得分:8)
为什么说“我必须在发送文件名后关闭客户端的写端”?您还没有完成发送数据,所以您肯定不想关闭套接字?
首先确定如何构建数据,以便接收方可以读取它并重建原始文件名和文件内容。您可能希望如何构建它的一些示例:
在您发送完整个结构后关闭套接字,无论您认为它是什么。
通过这些安排中的任何一种,接收方都拥有明确重建原始文件名和内容所需的所有信息。
更新:您在问题中添加了更多内容,这几乎是一个不同的问题......
您的服务器端代码(读取文件名和文件内容的代码)包含许多错误。
n
字节可用,您也会将第一个缓冲区数据中的n
个字节写入输出文件。实际上有n
减去文件名使用了很多。read()
和write()
进行任何错误检查,但我会假设您为了问题的清晰而忽略了这一点...... 在另一个大小的代码中,有一个明显的缓冲区溢出,你将1024字节读入一个只有1024 - len
字节可用的缓冲区。
您需要先解决所有这些问题,然后才能发挥作用。