程序中有两个进程,并且一个进程需要和另一个进程进行通信,那么可以使用管道,所谓的C/S模式也和这个差不多。
分为两端服务和客户端,下面简单说一下管道通信。两个类Server和Client,都包含如下方法:监听,接收,发送。
如下类:
Server类
public class Server
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern SafeFileHandle CreateNamedPipe(
String pipeName,
uint dwOpenMode,
uint dwPipeMode,
uint nMaxInstances,
uint nOutBufferSize,
uint nInBufferSize,
uint nDefaultTimeOut,
IntPtr lpSecurityAttributes);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int ConnectNamedPipe(
SafeFileHandle hNamedPipe,
IntPtr lpOverlapped);
public const uint DUPLEX = (0x00000003);
public const uint FILE_FLAG_OVERLAPPED = (0x40000000);
public class Client
{
public SafeFileHandle handle;
public FileStream stream;
}
public delegate void MessageReceivedHandler(Client client, string message);
public event MessageReceivedHandler MessageReceived;
public const int BUFFER_SIZE = 4096;
string pipeName;
Thread listenThread;
bool running;
List<Client> clients;
public string PipeName
{
get { return this.pipeName; }
set { this.pipeName = value; }
}
public bool Running
{
get { return this.running; }
}
public Server()
{
this.clients = new List<Client>();
}
public void Start()
{
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
this.running = true;
}
private void ListenForClients()
{
while (true)
{
SafeFileHandle clientHandle =
CreateNamedPipe(
this.pipeName,
DUPLEX | FILE_FLAG_OVERLAPPED,
0,
255,
BUFFER_SIZE,
BUFFER_SIZE,
0,
IntPtr.Zero);
if (clientHandle.IsInvalid)
return;
int success = ConnectNamedPipe(clientHandle, IntPtr.Zero);
if (success == 0)
return;
Client client = new Client();
client.handle = clientHandle;
lock (clients)
this.clients.Add(client);
Thread readThread = new Thread(new ParameterizedThreadStart(Read));
readThread.Start(client);
}
}
private void Read(object clientObj)
{
Client client = (Client)clientObj;
client.stream = new FileStream(client.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
byte[] buffer = new byte[BUFFER_SIZE];
//ASCIIEncoding encoder = new ASCIIEncoding();
UTF8Encoding encoder = new UTF8Encoding();//可以传汉字
while (true)
{
int bytesRead = 0;
try
{
bytesRead = client.stream.Read(buffer, 0, BUFFER_SIZE);
}
catch
{
break;
}
if (bytesRead == 0)
break;
if (this.MessageReceived != null)
this.MessageReceived(client, encoder.GetString(buffer, 0, bytesRead));
}
client.stream.Close();
client.handle.Close();
lock (this.clients)
this.clients.Remove(client);
}
public void SendMessage(string message)
{
lock (this.clients)
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] messageBuffer = encoder.GetBytes(message);
foreach (Client client in this.clients)
{
client.stream.Write(messageBuffer, 0, messageBuffer.Length);
client.stream.Flush();
}
}
}
}
Client类
public class Client
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern SafeFileHandle CreateFile(
String pipeName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplate);
public const uint GENERIC_READ = (0x80000000);
public const uint GENERIC_WRITE = (0x40000000);
public const uint OPEN_EXISTING = 3;
public const uint FILE_FLAG_OVERLAPPED = (0x40000000);
public delegate void MessageReceivedHandler(string message);
public event MessageReceivedHandler MessageReceived;
public const int BUFFER_SIZE = 4096;
string pipeName;
private FileStream stream;
private SafeFileHandle handle;
Thread readThread;
bool connected;
public bool Connected
{
get { return this.connected; }
}
public string PipeName
{
get { return this.pipeName; }
set { this.pipeName = value; }
}
public void Connect()
{
this.handle =
CreateFile(
this.pipeName,
GENERIC_READ | GENERIC_WRITE,
0,
IntPtr.Zero,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
if (this.handle.IsInvalid)
return;
this.connected = true;
this.stream = new FileStream(this.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
this.readThread = new Thread(new ThreadStart(Read));
this.readThread.Start();
}
public void Read()
{
byte[] readBuffer = new byte[BUFFER_SIZE];
ASCIIEncoding encoder = new ASCIIEncoding();
while (true)
{
int bytesRead = 0;
try
{
bytesRead = this.stream.Read(readBuffer, 0, BUFFER_SIZE);
}
catch
{
break;
}
if (bytesRead == 0)
break;
if (this.MessageReceived != null)
this.MessageReceived(encoder.GetString(readBuffer, 0, bytesRead));
}
this.stream.Close();
this.handle.Close();
}
public void SendMessage(string message)
{
//ASCIIEncoding encoder = new ASCIIEncoding();
UTF8Encoding encoder = new UTF8Encoding();//可以传汉字
byte[] messageBuffer = encoder.GetBytes(message);
this.stream.Write(messageBuffer, 0, messageBuffer.Length);
this.stream.Flush();
}
}
Server端
public class ServerPort
{
private Delegate sendMessage = null;
private ContainerControl mainForm;
public Server pipeServer = null;
public ServerPort(ContainerControl form,Delegate sendmessage)
{
mainForm = form;
sendMessage = sendmessage;
}
void SendMsg(string msg)
{
this.mainForm.Invoke(sendMessage, new Object[] { msg });
}
void PipeServer_MessageReceived(Server.Client client, string message)
{
if (!message.Equals(""))
{
SendMsg("接收到的信息是:" + message);
}
else
{
SendMsg("消息未收到???");
}
}
private void MessageSend()
{
}
public void PipServerStart()
{
try
{
if (!this.pipeServer.Running)
{
this.pipeServer.PipeName = "\\\\.\\pipe\\testprocesspipe";
this.pipeServer.Start();
this.pipeServer.MessageReceived += new Server.MessageReceivedHandler(PipeServer_MessageReceived);
}
}
catch
{
}
}
}
Client端,发送信息
public class ClientPort
{
private static Client pipeClient;
public static void MessagePipeStart()
{
if (pipeClient == null)
{
pipeClient = new Client();
pipeClient.MessageReceived += new Client.MessageReceivedHandler(pipeClient_MessageReceived);
}
if (!pipeClient.Connected)
{
pipeClient.PipeName = "\\\\.\\pipe\\testprocesspipe";
pipeClient.Connect();
}
if (pipeClient != null && pipeClient.Connected)
{
MessageSend("测试传输的字符:金胖子死了!!!");
}
}
static void MessageSend(string str)
{
pipeClient.SendMessage(str);
}
static void pipeClient_MessageReceived(string message)
{
}
}
启动服务端
ServerPort serverPort;
recivedMessage += new ServerRecivedMessageDelegate(DisplayMessage);
try
{
serverPort = new ServerPort(this, recivedMessage);
serverPort.pipeServer = new Server();
serverPort.PipServerStart();
}
catch
{ }
客户端发送信息
ClientPort.MessagePipeStart();
接收如图,
客户端发送后,服务端监听到,并接收
简单的例子下载地址:http://download.csdn.net/detail/yysyangyangyangshan/3946892
上述 只是在一个工程中简单的模拟。正的进程的通信,Server端和Client端分别在两个进程中,启动的方式都一样,当两端都启动的话,就可以互发信息了。当然,PipeName必须一致,双方才能接收到对方的信息。
这样,可以建造一个服务端,启动好几个Server设置PipeName 各不同,然后客户端分别对应不同的PipeName,就可实现服务器一对多的通信。