所以我试图制作一个程序,它发送一个文件,我想从我的客户端在我的主PC上打印,到我的第二台PC,运行服务器,并连接到打印机。当我测试我的代码时,我在我的主pc上运行客户端和服务器,它工作得很好。然而,当我在我的主PC上运行客户端,在我的第二台PC上运行服务器时,文件被损坏了,我不知道为什么。
这是我的Listener
(我删除了我认为不必要的部分):
void Listener()
{
//All of these strings and bools are filled correctly I just removed it because its long
string file="";
string size = "";
bool print;
Socket server = myList.AcceptSocket();
var output = File.Create(file);
Console.WriteLine("Client connected. Starting to receive the file");
int k = 0;
int read = 0;
byte[] buffer = new byte[long.Parse(size)];
NetworkStream stm = new NetworkStream(server);
while ((k = stm.Read(buffer, 0, buffer.Length-read)) > 0)
{
read += k;
}
output.Write(buffer, 0, buffer.Length);
output.Close();
if (print) { PrintFile(file); }
server.Close();
Thread.CurrentThread.Abort();
}
下面是客户端代码(我删除了我认为不必要的部分):
void startClient()
{
FileInfo f = new FileInfo(file);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(IPAddress.Parse("10.0.0.13"), 27015);
Console.WriteLine("Connected");
byte[] bytes = File.ReadAllBytes(file);
client.SendFile(file);
Console.WriteLine("File Sent");
client.Close();
}
有人知道怎么解决这个问题吗?提前感谢!
您不将read
偏移量应用于缓冲区,在每次NetworkStream.Read()
调用时开始在索引0处写入。在本地或使用较小的文件进行测试时,这将很好地工作,因为所有内容都将到达一个Read()
。在实际网络中或处理较大的文件时,您会发现需要多次Read()
调用才能读取所有数据。
所以改成:
stm.Read(buffer, read, buffer.Length-read)
您可能还需要重新考虑一次在内存中读取整个文件。您可能希望在此期间将其写入磁盘,特别是因为分配大型数组可能会导致OutOfMemoryException
比您预期的要早得多。
还要考虑使用现有的网络协议,而不是使用自己的网络协议。除了这个非常基本的问题之外,您还容易遇到许多其他常见的套接字陷阱。