我写了一个小程序,可以通过TCP接收巨大的字符串。
我只能从网络流中读取一次,然后程序崩溃。我该如何解决此问题,或者您可以建议我一种通过TCP发送大字符串的更好方法。客户端的缓冲区大小为202601176(字符串字节长度)。
这是我的代码:
namespace File_Transfer_Server
{
class Program
{
static void Main(string[] args)
{
TcpListener serverListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 6666);
serverListener.Start();
TcpClient tcpClient = serverListener.AcceptTcpClient();
Console.WriteLine(">>> Receiving");
byte[] clientBuffer = new byte[1024];
Console.WriteLine(clientBuffer.Length);
using (NetworkStream clientNStream = tcpClient.GetStream())
{
int i;
string received = "";
while ((i = clientNStream.Read(clientBuffer, 0, clientBuffer.Length)) > 0) //exception
{
string data = Encoding.ASCII.GetString(clientBuffer, 0, i);
received += data;
Console.WriteLine(data);
}
File.WriteAllText(@"E:\receivedData.txt", received);
Console.WriteLine(">>>Done");
}
}
}
}
这是例外:
Unhandled Exception: System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at File_Transfer_Server.Program.Main(String[] args) in D:\Files from PC\Visual Basic Projects - =&+Ivan+&=\Tesseract\Temp\File Transfer\File_Transfer_Server\Program.cs:line 29
编辑:
客户代码:
namespace File_Transfer_Client
{
class Program
{
static void Main(string[] args)
{
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 6666);
NetworkStream clientNetworkStream = client.GetStream();
string fileContent = FileBase64Encoding(@"D:\Download\AtomSetup-x64.exe");
byte[] fileBytes = Encoding.ASCII.GetBytes(fileContent);
// byte[] fileLength = Encoding.ASCII.GetBytes(fileBytes.Length.ToString());
Console.WriteLine(fileBytes.Length);
clientNetworkStream.Write(fileBytes, 0, fileBytes.Length);
Console.WriteLine("Send");
}
static string FileBase64Encoding(string path)
{
byte[] fileBytes = File.ReadAllBytes(path);
string fileBase64String = Convert.ToBase64String(fileBytes);
return fileBase64String;
}
}
}
答案 0 :(得分:0)
您的代码存在问题,即客户端在服务器设法接收所有数据之前关闭了连接。您必须告诉服务器您的消息长度。这称为“消息框架”。
可选步骤:确保没有任何Socket异常使客户端等待服务器,直到它接收到所有数据。服务器关闭连接。
客户代码:
static void Main(string[] args)
{
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 6666);
NetworkStream clientNetworkStream = client.GetStream();
string fileContent = FileBase64Encoding(@"D:\Download\AtomSetup-x64.exe");
byte[] fileBytes = Encoding.ASCII.GetBytes(fileContent);
// byte[] fileLength = Encoding.ASCII.GetBytes(fileBytes.Length.ToString());
Console.WriteLine(fileBytes.Length);
// Write the length of a message
var integerBytes = BitConverter.GetBytes(fileBytes.Length); // integer has 4 bytes
clientNetworkStream.Write(integerBytes, 0, integerBytes.Length);
// Write the contents
clientNetworkStream.Write(fileBytes, 0, fileBytes.Length);
Console.WriteLine("Send");
// Wait for server to finish receiving
clientNetworkStream.ReadByte();
Console.WriteLine("Connection closed");
}
static string FileBase64Encoding(string path)
{
byte[] fileBytes = File.ReadAllBytes(path);
string fileBase64String = Convert.ToBase64String(fileBytes);
return fileBase64String;
}
服务器代码:
class Program
{
static void Main(string[] args)
{
TcpListener serverListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 6666);
serverListener.Start();
TcpClient tcpClient = serverListener.AcceptTcpClient();
Console.WriteLine(">>> Receiving");
byte[] clientBuffer;
using (NetworkStream clientNStream = tcpClient.GetStream())
{
int i;
string received = "";
byte[] integerBytes = new byte[sizeof(int)];
clientNStream.Read(integerBytes, 0, integerBytes.Length); // receive message length
int messageLength = BitConverter.ToInt32(integerBytes, 0);
Console.WriteLine("Received message length: {0}", messageLength);
clientBuffer = new byte[messageLength]; // allocate buffer
clientNStream.Read(clientBuffer, 0, clientBuffer.Length); // read string contents
Console.WriteLine("Received all the data");
// we're done
Console.WriteLine("Closing connection");
tcpClient.Close();
received = Encoding.ASCII.GetString(clientBuffer, 0, clientBuffer.Length);
File.WriteAllText(@"E:\receivedData.txt", received);
Console.WriteLine(">>>Done");
}
}
}
如您所见,服务器代码现在更加简单。
理想情况下,您需要一种更高级的消息框架机制,该机制可以将消息分割成更小的块并直接写入文件,因为对于真正的大文件,您的内存将用完,将大消息分成较小的块。