现在对答案进行了彻底的改革。尽管我仍在尽我所能地发表评论,但我已尽量将其保持为“基本”/“一般”,而不会造成松散的结局。
主程序(普通法)
public async Task<byte[]> ConnectToCounterpart(string dataToSend)
{
// === Sending empty strings breaks the program ===
if (String.IsNullOrEmpty(dataToSend))
return null;
// === Variables n' Stuff ===
string counterPartIP = "127.0.0.1"; // The ip of the computer running counterpart program. (127.0.0.1 is the localhost/current computer).
int counterPartPort = 50_000; // The port which the counterpart program listens to
// === Getting a connection ===
TcpClient client = new TcpClient(counterPartIP, counterPartPort); // Connect to the counterpart program
NetworkStream nwStream = client.GetStream(); // Get the networkStream between the main and counterpart program
nwStream.ReadTimeout = 5_000; // Give the counterpart program 5 seconds to do its thing
// === Convert the "dataToSend" to a byte-array ===
byte[] bytesToSend = Encoding.UTF7.GetBytes(dataToSend); // An array with the bytes of the string (UTF7 lets you keep "cpecial characters like Æ, Ø, Å, Á etc.")
// === Send the file-bytes ===
await nwStream.WriteAsync(bytesToSend, 0, bytesToSend.Length); // Send the file-bytes to the counterpart program
// ==========================================
// At this point counterpart is doing work
// ==========================================
byte[] returnBytes = new byte[client.ReceiveBufferSize]; // The byte-array this method returns
try
{
// === Recieve the reply ===
int numberOfBytesRecieved = await nwStream.ReadAsync(returnBytes, 0, client.ReceiveBufferSize); // Receve the checksum from the counterpart and tthe ammount of sent bytes
// === Crop return-array to the recieved bytes ===
Array.Resize(ref returnBytes, numberOfBytesRecieved);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error while retrieving"); // Show error
returnBytes = null; // Set returnbytes to null
}
// === Close and dispose stream ===
nwStream.Close();
nwStream.Dispose();
// === Return the byte-array ===
return returnBytes;
}
在这段代码中,您可能已经注意到“async”、“Task<byte[]>”和“await”。 “Task<byte[]>”与“byte[]”(有点)相同,因为“async”修饰符需要它,所以使用它。 (关于异步编程:https://msdn.microsoft.com/da-dk/library/hh156513(v=vs.110).aspx)
在任何情况下返回的类型仍然是“byte[]”。 “Async”和“Await”将在一个“位”(Byte, bit... Puns)中进一步解释。
对应代码(BackgroundWorker)
private void BackgroundWorkerCalculate_Counterpart_DoWork(object sender, DoWorkEventArgs e)
{
// === Variables n' Stuff ===
int listeningPort = 50_000; // The port which the counterpart program listens to
// === Start listening ===
TcpListener listener = new TcpListener(IPAddress.Any, listeningPort); // Listen to the port
listener.Start();
// Infinite loop for infinite computations
while (true)
{
// === Getting a connection ===
TcpClient connection = listener.AcceptTcpClient();
NetworkStream nwStream = connection.GetStream();
// === Get the recieved bytes ===
byte[] recievedBytes = new byte[connection.ReceiveBufferSize]; // Create a buffer for the incomming file-bytes
int numberOfBytesRecieved = nwStream.Read(recievedBytes, 0, connection.ReceiveBufferSize); // Read the bytes to the buffer
// === Convert recieved bytes to a string ===
string recievedString = Encoding.UTF7.GetString(recievedBytes, 0, numberOfBytesRecieved);
// === Understanding the recieved data ===
/* Lets say recievedString == "[path]" */
byte[] replyBytes = new byte[] { 1 }; // Bytes to reply to the main program
try
{
using (MD5 md5 = MD5.Create()) // Create the hashing protocol
{
using (FileStream fileStream = new FileStream(recievedString, FileMode.Open)) // Open the file to hash
{
replyBytes = md5.ComputeHash(fileStream); // replyBytes now contains the hash
}
}
}
catch
{ } // If file doesn't exist, then replyBytes stays as { 1 }, which will be returned if things goes wrong
// === Send the reply to main program ===
nwStream.Write(replyBytes, 0, replyBytes.Length);
}
}
此代码仍然执行相同的操作:接收一些数据并返回一些数据。您现在可以根据需要修改“了解收到的数据”部分。例如检查接收到的路径是文件还是目录,从而区分“GetChecksum”(指文件)和“GetSubelements”(指目录)。
主程序(用法)
private async void ButtonCalculate_Counterpart_Click(object sender, EventArgs e)
{
// This is how you use the method
byte[] replyBytes = await ConnectToCounterpart(@"folder\file.txt");
// "async" makes the given method "asyncronous", so that it runs parallell to other tings
// "await" will prevent a time-consumeing method-call from "halting" or "blocking" the main process.
// Check if things went wrong
if (replyBytes == new byte { 1 }) // As mentioned ealier in the backgroundWorker code
{
MessageBox.Show("Something went wrong with the hashing. Is the path correct?", "Could not hash")
return;
}
// If you want the reply as a normal string
string replyString = Encoding.UTF7.GetString(replyBytes, 0, replyBytes.Length);
// If you want the reply as a checksum
string checkSum = BitConverter.ToString(replyBytes);
}
这里的cmets应该解释一下。
注意:您可以轻松使用除 UTF7 之外的其他加密方式,只需在整个代码中保持一致即可。
注意 2:如果发送的数据大于 50 kB,则存在并非所有数据都被发送的风险,因为我对此进行了编程。如果这成为一个问题,我可以做一些改变。这些变化更加复杂。
注意 3:如果您想从单独的网络(通过互联网而不是本地)访问对方,那么您需要在对方所连接的路由器上进行一些端口转发。
注意 4:请记住,如果您将“Folder\File.txt”这样的路径传递给对方,那么对方将查看目录“C:\Users\...\...\FolderWithProgramExe\Folder\File.txt”。如果您改为将“C:\Folder\File.txt”(注意开头为“C:\”)传递给对方,那么对方将准确查看计算机上的位置“C:\Folder\File.txt”。
我希望这对你现在有用。如前所述,我已尝试将代码保持为“可塑性”/“易于修改”,以便您可以根据需要对其进行调整。