问题
Good day,
I have a client application which sends to the server a lists of application the client opens. It particulary sends the file path, file name and hostname. My problem is the sent data should be serialize and deserialize when it is received in the server. I am new to C# so I have very little idea of Serialization.
This is the client side
private List<int> listedProcesses = new List<int>();
private void SendData()
{
String processID = "";
String processName = "";
String processPath = "";
String processFileName = "";
String processMachinename = "";
listBox1.BeginUpdate();
try
{
piis = GetAllProcessInfos();
for (int i = 0; i < piis.Count; i++)
{
try
{
if (!listedProcesses.Contains(piis[i].Id)) //placed this on a list to avoid redundancy
{
listedProcesses.Add(piis[i].Id);
processID = piis[i].Id.ToString();
processName = piis[i].Name.ToString();
processPath = piis[i].Path.ToString();
processFileName = piis[i].FileName.ToString();
processMachinename = piis[i].Machinename.ToString();
output.Text += "\n\nSENT DATA : \n\t" + processFileName + "\n\t" + processMachinename + "\n\t" + processID + "\n\t" + processName + "\n\t" + processPath + "\n";
}
}
catch (Exception ex)
{
wait.Abort();
output.Text += "Error..... " + ex.StackTrace;
}
NetworkStream ns = tcpclnt.GetStream();
String data = "";
data = "--++" + " " + processFileName + " " + processMachinename + " " + processID + " " + processPath;
if (ns.CanWrite)
{
byte[] bf = new ASCIIEncoding().GetBytes(data);
ns.Write(bf, 0, bf.Length);
ns.Flush();
}
}
}
finally
{
listBox1.EndUpdate();
}
}
private void cmd_dis_Click(object sender, EventArgs e)
{
if (wait != null)
{
wait.Abort();
//read.Close(2000);
}
IPAddress ipclient = Dns.GetHostByName(Dns.GetHostName()).AddressList[0];
String ipclnt = "+@@+" + ipclient.ToString();
NetworkStream ns = tcpclnt.GetStream();
if (ns.CanWrite)
{
byte[] bf = new ASCIIEncoding().GetBytes(ipclnt);
ns.Write(bf, 0, bf.Length);
ns.Flush();
}
tcpclnt.Close();
// read.Close();
Application.Exit();
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
ProcessInfoItem pii = piis.FirstOrDefault(x => x.Id == (int)(sender as ListBox).SelectedValue);
if (pii != null)
{
string hostName = System.Net.Dns.GetHostName();
textBox4.Text = listBox1.SelectedValue.ToString();
textBox5.Text = (pii.FileName);
textBox6.Text = (pii.Path);
textBox7.Text = (pii.Machinename);
}
}
private List<ProcessInfoItem> piis = new List<ProcessInfoItem>();
private void Form1_Load(object sender, EventArgs e)
{
piis = GetAllProcessInfos();
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "Id";
listBox1.DataSource = piis;
}
private List<ProcessInfoItem> GetAllProcessInfos()
{
List<ProcessInfoItem> result = new List<ProcessInfoItem>();
Process currentProcess = Process.GetCurrentProcess();
Process[] processes = Process.GetProcesses();
foreach (Process p in processes)
{
if (!String.IsNullOrEmpty(p.MainWindowTitle))
{
//ProcessInfoItem pii = new ProcessInfoItem(p.Id, p.MainModule.ModuleName, p.MainModule.FileName, p.MainWindowTitle);
ProcessInfoItem pii = new ProcessInfoItem(p.Id, p.MainModule.ModuleName, p.MainWindowTitle, p.MainModule.FileName, Environment.MachineName);
result.Add(pii);
}
}
return result;
}
public class ProcessInfoItem
{
public int Id { get; set; }
public string Name { get; set; }
public string FileName { get; set; }
public string Path { get; set; }
public string Machinename { get; set; }
public ProcessInfoItem(int id, string name, string filename, string path, string machinename)
{
this.Id = id;
this.Name = name;
this.FileName = filename;
this.Path = path;
this.Machinename = machinename;
}
}
and here is the server which needs to be deserialize
private void recieveData()
{
NetworkStream nStream = tcpClient.GetStream();
ASCIIEncoding ascii = null;
while (!stopRecieving)
{
if (nStream.CanRead)
{
byte[] buffer = new byte[1024];
nStream.Read(buffer, 0, buffer.Length);
ascii = new ASCIIEncoding();
recvDt = ascii.GetString(buffer);
/*Received message checks if it has +@@+ then the ip is disconnected*/
bool f = false;
f = recvDt.Contains("+@@+");
if (f)
{
string d = "+@@+";
recvDt = recvDt.TrimStart(d.ToCharArray());
clientDis();
stopRecieving = true;
}
//else if (recvDt.Contains("^^"))
//{
// new Transmit_File().transfer_file(file, ipselected);
//}
/* ++-- shutsdown/restrt/logoff/abort*/
else if (recvDt.Contains("++--"))
{
string d = "++--";
recvDt = recvDt.TrimStart(d.ToCharArray());
this.Invoke(new rcvData(addToOutput));
clientDis();
}
/*--++ Normal msg*/
else if (recvDt.Contains("--++"))
{
string d = "--++";
recvDt = recvDt.TrimStart(d.ToCharArray());
this.Invoke(new rcvData(addToOutput));
}
}
Thread.Sleep(1000);
}
}
public void addToOutput()
{
if (recvDt != null && recvDt != "")
{
output.Text += "\n Received Data : " + recvDt;
recvDt = null;
}
}
Thank you.
回答1:
You basically need Interprocess Communication.
As an option you can use WCF for communication between your client and server application.
You can create a service and host it in an application that will be receive data from other application and consume service in other application to send data and show response.
Here is an example of the doing it in a simple way. In this sample I have created 2 applications. Application2 Sends a data to Application1 automatically once in each 10 secconds and Application1 sends a response back to Application2 and Application2 will show response.
To run sample codes follow this steps:
- Create a soloution with 2 console applications, Application1 and Application2
- Add System.ServiceModel reference to both projects.
- Paste below codes in program.cs of each project.
- Right click on solution and in Properties, make solution Multi startup projects and set Action of each project 'Start'
- Press Ctrl+F5 to run projects
- In Application1 window you will see a service is running message.
- Application2 will send DateTime.Now to Application 2 every 10 secconds and will receive a respone from Application 2 and display it it Application1 Window.
Application1 Program.cs
using System;
using System.ServiceModel;
namespace Application1
{
[ServiceContract]
public interface IEchoService
{
[OperationContract]
string Echo(string value);
}
public class EchoService : IEchoService
{
public string Echo(string value)
{
return string.Format("You send me data'{0}'", value);
}
}
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(EchoService), new Uri[] { new Uri("http://localhost:8000") }))
{
host.AddServiceEndpoint(typeof(IEchoService), new BasicHttpBinding(), "Echo");
host.Open();
Console.WriteLine("Service is running...");
Console.WriteLine("Press Enter to exit if you want to close service.");
Console.ReadLine();
host.Close();
}
}
}
}
Application2 Program.cs
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace Application2
{
[ServiceContract]
public interface IEchoService
{
[OperationContract]
string Echo(string value);
}
class Program
{
static void Main(string[] args)
{
//In real implementation, use server IP instead of localhost
ChannelFactory<IEchoService> factory = new ChannelFactory<IEchoService>(new BasicHttpBinding(), new EndpointAddress("http://localhost:8000/Echo"));
IEchoService proxy = factory.CreateChannel();
int processedSeccond = 0;
while (true)
{
var dateTime = DateTime.Now;
if (dateTime.Second % 10 == 0 && dateTime.Second!=processedSeccond)
{
processedSeccond = dateTime.Second;
string data= dateTime.ToString(); //or Console readLine for manual data entry
Console.WriteLine("Recieved Response: " + proxy.Echo(str));
}
}
}
}
}
Result
It's that simple. You can change codes to your desire.
An an example of passing complex data to service:
[DataContract]
public class MyMessageClass
{
[DataMember]
public string MyValue1 {get;set;}
[DataMember]
public string MyValue2 {get;set;}
}
Then you can update the interface and inplementation of service and simply use it without need to serialize and deserialize anything, all things will be done by WCF behind the scene.
Pleae note you can use WCF Services with both Windows Forms Applications and Console Applications and you can continue to develop your project the same way you are doing. The only change you need is to add a service to the application that will run on server and then consume that service in application that will run on client. It is not related to logic of your application all. And the samples that I provided is in Console Application just for sake of simplicity.
来源:https://stackoverflow.com/questions/32692710/send-information-between-applications