我有tcpclient的问题,我需要发送一个或多个文件,所以我有一个服务器和客户端的应用程序,协议是这样的:
1)我发送一些字符串,其中包含有关文件数量,文件名称及其大小的信息,所有这一切都与streamwriter.writeline(从具有该功能的服务器接收) streamreader.readline)
2)在这些字符串之后,我发送文件,在每个文件之后,服务器使用" ACK"的streamwriter.writeline回答客户端。该文件随之发送 networkstream.write方法,并通过networkstream.read接收。
问题是服务器读取直到接收的字节数等于文件大小,但是......尽管客户端"似乎"发送文件的每个字节,服务器 总共收到更少的字节!因此,在此步骤中应用程序被阻止,服务器正在等待下一个字节,并且客户端正在等待" ACK" 使用streamreader.readline发送下一个文件或只是为了完成操作。
我还想查看服务器收到的内容,因此我打印了在读取周期中收到的字节数,发现有时服务器读取的字节数少于流的缓冲区大小(固定为1024)。这应该是正常的,因为TCP尽快读取,它应该不是真正的问题,对吧?我不能 相信tcp丢失字节,但我不知道如何解决。
您可以在这里找到代码的一部分:
----服务器端----------
..........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();
}
---------客户端结束------
所以...有人可以帮助我摆脱这个地狱??? THX:)