C# tcpclient读取的字节数少于预期
我的tcpclient有问题,我需要发送一个或多个文件,因此我有一个带有服务器和客户端的应用程序,协议如下: 1) 我通过streamwriter.writeline(通过函数从服务器接收)发送一些字符串,其中包含有关文件数量、文件名及其大小的信息 streamreader.readline) 2) 在这些字符串之后,我发送文件,在每个文件之后,服务器使用streamwriter.writeline“ACK”向客户机应答。该文件随 networkstream.write方法,并通过networkstream.read接收 问题是服务器一直读取,直到收到的字节等于文件大小,但是。。。尽管客户端“似乎”发送文件的每个字节,但服务器 接收的字节总数更少!因此,应用程序在此步骤中被阻止,服务器正在等待下一个字节,客户端正在等待“ACK”字符串 在发送下一个文件或仅完成操作之前使用streamreader.readline 我还想检查服务器接收到什么,所以我打印了读取周期中接收到的字节数,发现有时服务器读取的字节数少于流的缓冲区大小(固定为1024)。这应该是正常的,因为TCP会尽快读取,这不应该是真正的问题,对吗?我不能 相信tcp会丢失字节,但我不知道如何解决 在这里您可以找到部分代码: ----服务器端---------- ----服务器端结束-------------- --------客户端--------------C# tcpclient读取的字节数少于预期,c#,byte,tcpclient,networkstream,C#,Byte,Tcpclient,Networkstream,我的tcpclient有问题,我需要发送一个或多个文件,因此我有一个带有服务器和客户端的应用程序,协议如下: 1) 我通过streamwriter.writeline(通过函数从服务器接收)发送一些字符串,其中包含有关文件数量、文件名及其大小的信息 streamreader.readline) 2) 在这些字符串之后,我发送文件,在每个文件之后,服务器使用streamwriter.writeline“ACK”向客户机应答。该文件随 networkstream.write方法,并通过network
…做一些事情。。。。
//sw是streamWriter,Sr是streamReader,stream是networkstream
System.Collections.Specialized.StringCollection formats=剪贴板.GetFileDropList();
sw.WriteLine(“客户端:文件:“+formats.Count+”*”);
sw.Flush();
//发送到服务器的文件名和相对大小
foreach(格式为字符串文件名)
{
//好吧,我的协议有道理……忽略它。
sw.WriteLine((Directory.Exists(filename))?System.IO.Path.GetFileName(filename)+“*”:System.IO.Path.GetFileName(filename));
sw.Flush();
FileStream Fs=newfilestream(文件名,FileMode.Open,FileAccess.Read);
软件写入线(Fs长度);
sw.Flush();
stream.Flush();
Fs.Close();
}
//发送文件
foreach(格式为字符串文件名)
{
//client_sync是包装TcpClient套接字的类
客户端同步。发送单个文件(流、文件名);
resp=sr.ReadLine();
}
…正在做一些事情并结束此功能。。。
发送文件功能的定义如下:
(注意:我几周前从代码项目中获取了此函数)
public void发送单文件(NetworkStream netstream,字符串文件名)
{
//连接是我班的一个参数
如果(!已连接)返回;
字节[]SendingBuffer=null;
尝试
{
FileStream Fs=newfilestream(文件名,FileMode.Open,FileAccess.Read);
int NoOfPackets=Convert.ToInt32(数学上限(Convert.ToDouble(Fs.Length)/Convert.ToDouble(this.BufferSize));
//注意:缓冲区大小为1024
int TotalLength=(int)Fs.Length,CurrentPacketLength=0;
int bytes_send=0;
for(int i=0;i此.BufferSize)
{
CurrentPacketLength=此.BufferSize;
TotalLength=TotalLength-当前包装长度;
}
其他的
CurrentPacketLength=总长度;
SendingBuffer=新字节[CurrentPacketLength];
Fs.Read(发送缓冲区,0,CurrentPacketLength);
netstream.Write(SendingBuffer,0,SendingBuffer.Length);
字节\u发送+=当前包长度;
}
Fs.Close();
}
捕获(例外情况除外)
{
netstream.Close();
//我的职能
关闭_连接();
}
netstream.Flush();
}
---------客户端结束------
所以…有人能帮我逃离这个地狱???THX:)简短版本:您可能不应该将文本阅读器/写入器与流混合使用。StreamReader类缓冲数据,并且可能正在获取一些用于传输二进制部分的字节。您可以自己处理文本解码,这样您就可以控制缓冲,或者使用FTP之类的控制通道设计(其中一个连接以文本形式交换命令,另一个通道以交换二进制数据)。好的,谢谢!我试图消除StreamWriter或StreamReader的每个实例,只使用NetworkStream进行通信。它很有效!
..........Doing Stuffs.............
//secServer is the TCPListener socket.
this.secSHandler = secServer.AcceptTcpClient();
this.secSHandler.ReceiveBufferSize = 1024;
this.secSHandler.SendBufferSize = 1024;
this.is_connected_now = true;
print("is connected!!! ");
//Taking streams...
this.stream = this.secSHandler.GetStream();
this.sr = new StreamReader(stream);
this.sw = new StreamWriter(stream);
string first = sr.ReadLine();
print("I read + " + first + " .");
int numFiles = 0;
string connType = first.Substring(0, 6);
if (connType.CompareTo("CLIENT") == 0)
{
//SINCR CLIENT -> SERVER
string clipType = first.Substring(7, 4);
if (clipType.CompareTo("FILE") == 0)
{
//CASE RECEIVE FILE
int posSeparator = first.IndexOf('*');
string nFiles = first.Substring(12, first.Length - 13);
numFiles = Convert.ToInt16(nFiles);
string[] fileNames = new string[numFiles];
int[] fileSizes = new int[numFiles];
//TAKE FROM THE CLIENT ALL FILE NAMES AND SIZES
for (int i = 0; i < numFiles; i++)
{
fileNames[i] = sr.ReadLine();
print("Name file : I read " + fileNames[i]);
string dim = sr.ReadLine();
fileSizes[i] = Convert.ToInt32(dim);
print("Size file : I read " + fileSizes[i]);
}
//RECEVING FILES
for (int i = 0; i < numFiles; i++)
{
receive_single_file_1(stream, fileSizes[i], fileNames[i]); //CANNOT GO AFTER THIS POINT
sw.WriteLine("File sent - number " + i);
sw.Flush();
}
}
}
.............Doing others stuffs.............
sr.Close();
sw.Close();
public bool receive_single_file_1(NetworkStream netstream, int size, string filename)
{
int sizeToRead = 0;
string f_name = "";
//...f_name is the result of another operation, for the sake of the example i write only the final instruction
f_name = filename;
byte[] RecData = new byte[1024];
int RecBytes = 0;
try
{
int totalrecbytes = 0;
FileStream Fs = new FileStream((tempFold + f_name), FileMode.OpenOrCreate, FileAccess.Write);
//COUNTER OF THE WHILE
int nciclo = 0;
while ((RecBytes = netstream.Read(RecData, 0, 1024)) > 0)
{
//I defined print in another context...
totalrecbytes += RecBytes;
if(RecBytes!=1024)
print("Cycle : "+ nciclo +" Content RecBytes : " + RecBytes + " e RecData.Length : " + RecData.Length + " byte reads : " + totalrecbytes + ".");
Fs.Write(RecData, 0, RecBytes);
if (totalrecbytes >= size)
{
print("Read all bytes " + totalrecbytes + " over " + size + " .");
break;
}
//Refresh the buffer
RecData = new byte[1024];
nciclo++;
}
print("End of transfer. Received " + totalrecbytes + "File :" + filename + " Saved on " + tempFold);
Fs.Close();
}
catch (Exception ex)
{
//Ok here i return false, but i do some other stuff before
return false;
}
return true;
}
.....DOING STUFFS....
//sw is the streamWriter, Sr the streamReader and the stream is the networkstream
System.Collections.Specialized.StringCollection formats = Clipboard.GetFileDropList();
sw.WriteLine("CLIENT:FILE:" + formats.Count + "*");
sw.Flush();
//Sending to the server filename and relative size
foreach (string filename in formats)
{
//Ok the * has sense in my protocol...ignore it.
sw.WriteLine((Directory.Exists(filename)) ? System.IO.Path.GetFileName(filename) + "*" : System.IO.Path.GetFileName(filename));
sw.Flush();
FileStream Fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
sw.WriteLine(Fs.Length);
sw.Flush();
stream.Flush();
Fs.Close();
}
//Sending files
foreach (string filename in formats)
{
//client_sync is the class that wrap the TcpClient socket
client_sync.send_single_file(stream, filename);
resp = sr.ReadLine();
}
....DOING STUFF AND end of this function...
The send file function is defined in this way :
(note : i take this function from code project some weeks ago)
public void send_single_file(NetworkStream netstream, string filename)
{
//connected is a param of my class
if (!connected) return;
byte[] SendingBuffer = null;
try
{
FileStream Fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
int NoOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(Fs.Length) / Convert.ToDouble(this.BufferSize)));
//NOTE: BUFFERSIZE IS 1024
int TotalLength = (int)Fs.Length, CurrentPacketLength = 0;
int bytes_send = 0;
for (int i = 0; i < NoOfPackets; i++)
{
if (TotalLength > this.BufferSize)
{
CurrentPacketLength = this.BufferSize;
TotalLength = TotalLength - CurrentPacketLength;
}
else
CurrentPacketLength = TotalLength;
SendingBuffer = new byte[CurrentPacketLength];
Fs.Read(SendingBuffer, 0, CurrentPacketLength);
netstream.Write(SendingBuffer, 0, SendingBuffer.Length);
bytes_send += CurrentPacketLength;
}
Fs.Close();
}
catch (Exception ex)
{
netstream.Close();
//my function
close_connection();
}
netstream.Flush();
}