我正在编写一个小而简单的服务器(用于Linux工作站的C语言)。
客户端向我的服务器请求文件,我的服务器将此文件询问另一台将其发送到我的服务器的服务器。
我的服务器在将文件发送到客户端之前不应该收到所有文件但是必须在文件到达时发送文件的字节。
这是学校的一项练习,所以我不能脱离这个要求。
我已经实现了下面解释的功能。问题是客户端收到的是非确定数量的字节,而且不是整个文件。
int Recv_and_send_file (int socketa, int socketb, char *buffer, size_t file_size){
size_t n;
ssize_t nread;
ssize_t nwritten;
char c;
for (n=1; n<file_size; n++)
{
nread=recv(socketa, &c, 1, 0);
if (nread == 1)
{
nwritten = send(socketb,&c,1,0);
}
else if (nread == 0)
{
*buffer = 0;
return (-1); /* Errore */
}
else
return (-1); /* Errore */
}
}
*buffer = 0;
return (n);
}
有人可以告诉我我哪里错了吗?
在服务器和客户端上更改值SO_SNDBUF和SO_RCVBUF是一个愚蠢的想法吗?
答案 0 :(得分:1)
假设file_size
是您要发送的总字节数,那么for
循环将只发送file_size - 1
个字节。换句话说,你是一个人。从0
开始,而不是解决此问题:
for (n=0; n<file_size; n++)
{ //..
您捕获send()
的返回值,但不检查它是否成功。
您正在处理来自0
的{{1}}返回值与错误相同。由于您在从函数返回recv()
后没有显示您执行的操作,因此我不知道这是否会导致您的问题。
-1
和send()
上的某些错误是“软”,因为您可以针对这些特定错误重试该操作。其中一个错误是recv()
,但请检查系统上的文档以查看是否有其他错误。
答案 1 :(得分:1)
为了优化性能并简化代码,您可以使用splice()+管道。 Sendfile使您可以在文件描述符之间“转发”数据,而无需将副本复制到用户空间。
答案 2 :(得分:1)
您确定已复制了正确的代码吗?因为它不会编译,所以在最后一个中有一个}与相应的{。
不匹配。另外,您如何了解文件大小?如果它通过套接字作为整数发送,请记住源和目标机器的可能字节顺序。
无论如何,你一次只读一个字节,你应该这样改进:
编辑:使用缓冲区而不是额外的buff [2048];
int Recv_and_send_file (int socketa, int socketb, char *buffer, size_t file_size){
ssize_t nread;
ssize_t nwritten;
ssize_t bLeft=file_size;
while (bLeft > 0)
{
nread=recv(socketa, buffer, bleft, 0);
if (nread > 0)
{
nwritten = send(socketb, buffer, nread, 0);
bLeft -= nread;
buffer+=nread;
}
else if (nread == 0)
{
// I think this could raise a memory exception, read below
*buffer = 0;
return (-1); /* Errore */
}
else
{
return (-1); /* Errore */
}
}
// If buffer is allocated with file_size bytes this one will raise a memory exception
// *buffer = 0;
return (file_size-bLeft);
}