这并不总是发生。但它比完全接收字节更经常发生。
这是我的客户端prog如何将字节发送到我的服务器prog:
public void sendBytes()
{
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
TcpClient cli = tcpServer; //tcpServer is a global TcpClient variable I use to connect to the server.
NetworkStream ns = cli.GetStream();
CopyStreamToStream(fs, ns, null);
ns.Flush();
}
public static void CopyStreamToStream(Stream source, Stream destination, Action<Stream, Stream, Exception> completed)
{
byte[] buffer = new byte[0x1000];
int read;
while ((read = source.Read(buffer, 0, buffer.Length)) > 0) // <- client loop
destination.Write(buffer, 0, read);
}
这是我的服务器编程从我的客户端prog接收字节的方式:
FileStream ms = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
do
{
int szToRead = s.Available; //s is a socket
byte[] buffer = new byte[szToRead];
int szRead = s.Receive(buffer, szToRead, SocketFlags.None);
if (szRead > 0)
ms.Write(buffer, 0, szRead);
}
while(s.Available != 0); //i also tried ms.length < size_of_file_to_be_received_in_bytes
我进入程序并观察了值,我不知道是什么原因导致缺少字节。我不知道问题出在客户端程序或服务器程序上。
我不知道这是否相关,但是当我尝试进入客户端循环(观察fs.length的值并检查它是否会在服务器中接收)时,所有4次尝试发送文件从客户端到服务器成功。但是当我没有观察客户端循环,只看服务器应用程序(查看ms.length的值)时,只有4次尝试将文件发送到服务器成功。在3次失败的尝试中,ms.length小于源文件的字节数(我在文件的属性中检查了它)。
This是我从
开始的其他信息:
在原始代码上(来自我基于程序的网站),循环有不同的条件:
FileStream ms = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
do
{
int szToRead = s.Available; //s is a socket
byte[] buffer = new byte[szToRead];
int szRead = s.Receive(buffer, szToRead, SocketFlags.None);
if (szRead > 0)
ms.Write(buffer, 0, szRead);
}
while(SocketConnected(s)); // <--- i changed this in my program
private static bool SocketConnected(Socket s)
{
return !(s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0));
}
我认为SocketConnected测试套接字是否仍然连接,因为客户端程序的原始代码是这样的:
CopyStreamToStream(fs, ns, null);
ns.Flush();
ns.Close();
我从程序中删除了ns.Close(),因为我想维护客户端应用程序与服务器的连接。所以我希望能够检查我是否已经完成了从客户端应用程序读取的所有字节,而没有从客户端关闭套接字连接。
答案 0 :(得分:4)
如果Available为零,这并不意味着您已完成读取字节。这意味着目前,在这纳秒内,没有排队的字节。服务器怎么知道将来会有多少字节?
在很好的近似中,每次使用可用都是错误的!
删除可用的所有用法。相反,总是尝试读取完整的缓冲区。如果你得到0,这意味着套接字已经关闭,你就完成了。
编辑:这是一些规范的阅读代码:
var buffer = new byte[8192];
while(true) {
var readCount = stream.Read(buffer, 0, buffer.Length);
if (readCount == 0) break;
outputStream.Write(buffer, 0, readCount);
}