???? 最近因项目需要,需要用到socket,需求是这样的,有很多台收集数据的服务器,另有三台用于监视的服务器,收集服务器向监视服务器发消息,然后监视服务器收到消息,改变相应灯的颜色。然后其中有两个窗体需要互相切换,后面决定用两个不同的端口去监听,这样就不会有数据丢失,因为发送可能同时往两个端口发消息。在这过程序中遇到很多问题,但现在很多问题都已解决了,由于任务时间紧,没有及时把遇到的问题发出来,也没有把解决方案记录下来,现在有很多都不知道怎么解决了。
?
???? 本人对java比较了解,对c#是门外汉,只有查资料,遇到问题就去百度,谷歌,我常去谷歌,习惯问题。现在因为总共有四个画面,然后写了个基类BaseForm,socket通信的服务器端代码封装到一个类里,因为想到公用,所以将这个服务器端类让他成为BaseForm的成员变量,想到什么时候开启服务,什么时候关闭服务,因为以前写过VB的程序,对WINFORM开发还是有所了解,只是发展太快,有很多年都没整了,很多东西就只有查呀,因为客户那边收集服务器发过来的消息分别用了28个端口来发的,服务器收也是用的28个端口来收的,因为每分钟都要发一次,数据大概10秒左右收集完毕,然后就在15或更后向服务器端发消息,然后在监视的服务器上实时的显示相应的状态。期间遇到些问题在这里说一下,
?? 1.有时候出现在绑定端口时出错,后面加了try catch就没有问题了,具体错误号记不得了,有时在收数据的时候出错
?? 2.控件跨线程访问,因为服务器上为了好调试,加了一个收到消息的显示控件,还有就是需要根据收到的消息及IP地址来显示相应位置的信息,Control.CheckForIllegalCrossThreadCalls = false;加了这句话就没问题了,控件就可以跨线程序访问了
? 3.经常出现访问已被回收的对象,因为用到异步通信,搞不懂该怎么回收资源,最后乱整整好了,好像是把开启的线程关了,把监听端口关了。
? 4.收到的数据怎么让他显示在相应的form上,后面经对c#比较熟的同事指点了下,说用委托,事件,后面就查了下MSDN,最后还还是用的事件,另外说一下,以前曾理解委托是怎么用了,结果久了不了,又忘了,好像当时想到委托就像是JAVA里的代理。晕了,搞不清楚,反正很少用,用的时候再说吧。
?
先说到上面这点吧,文笔有点差,大家将就看哈,从小语文就一直不及格。呵呵
?
?
先看一下用于发数据的客户端代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Threading; using System.Net; namespace ClientSocketConsoleApplication { // State object for receiving data from remote device. public class StateObject { // Client socket. public Socket workSocket = null; // Size of receive buffer. public const int BufferSize = 256; // Receive buffer. public byte[] buffer = new byte[BufferSize]; // Received data string. public StringBuilder sb = new StringBuilder(); } public class AsynchronousClient { // The port number for the remote device. //private const int port = 11000; // ManualResetEvent instances signal completion. private static ManualResetEvent connectDone = new ManualResetEvent(false); private static ManualResetEvent sendDone = new ManualResetEvent(false); private static ManualResetEvent receiveDone = new ManualResetEvent(false); // The response from the remote device. private static String response = String.Empty; string ip ; string port; public AsynchronousClient(String remoIP, String remoport) { ip = remoIP; port = remoport; } public void StartClient() { // Connect to a remote device. try { // Establish the remote endpoint for the socket. // The name of the // remote device is "host.contoso.com". int serverPort = Convert.ToInt32(port); IPAddress ipAddress = IPAddress.Parse(ip);// ipHostInfo.AddressList[0]; IPEndPoint remoteEP = new IPEndPoint(ipAddress,serverPort); IPHostEntry ipHostInfo = Dns.GetHostByAddress(remoteEP.Address); // Create a TCP/IP socket. Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Connect to the remote endpoint. client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); connectDone.WaitOne(); Console.WriteLine("enter message!"); String message = System.Console.ReadLine(); // Send test data to the remote device. Send(client, message+"<EOF>"); sendDone.WaitOne(); // Receive the response from the remote device. Receive(client); receiveDone.WaitOne(); // Write the response to the console. Console.WriteLine("Response received : {0}", response); // Release the socket. client.Shutdown(SocketShutdown.Both); client.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } private static void ConnectCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object. Socket client = (Socket)ar.AsyncState; // Complete the connection. client.EndConnect(ar); Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString()); // Signal that the connection has been made. connectDone.Set(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } private static void Receive(Socket client) { try { // Create the state object. StateObject state = new StateObject(); state.workSocket = client; // Begin receiving the data from the remote device. client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); } catch (Exception e) { Console.WriteLine(e.ToString()); } } private static void ReceiveCallback(IAsyncResult ar) { try { // Retrieve the state object and the client socket // from the asynchronous state object. StateObject state = (StateObject)ar.AsyncState; Socket client = state.workSocket; // Read data from the remote device. int bytesRead = client.EndReceive(ar); if (bytesRead > 0) { // There might be more data, so store the data received so far. state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); // Get the rest of the data. client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); } else { // All the data has arrived; put it in response. if (state.sb.Length > 1) { response = state.sb.ToString(); } // Signal that all bytes have been received. receiveDone.Set(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } } private static void Send(Socket client, String data) { // Convert the string data to byte data using ASCII encoding. byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device. client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client); } private static void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object. Socket client = (Socket)ar.AsyncState; // Complete sending the data to the remote device. int bytesSent = client.EndSend(ar); Console.WriteLine("Sent {0} bytes to server.", bytesSent); // Signal that all bytes have been sent. sendDone.Set(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } //public static int Main(String[] args) //{ // StartClient(); // return 0; //} } }
?启动类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using yokohama.socketClient; namespace ClientSocketConsoleApplication { class Program { static void Main(string[] args) { AsynchronousClient client; if (args != null || args.Length == 2) { client = new AsynchronousClient(args[0], args[1]); client.StartClient(); } } } }
?socket监听类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Net; using System.Threading; namespace yokohama.socket { public class AsynchronousSocketListener { public event EventHandler<SocketEventArgs> ReceiveCustomEvent; // Thread signal. //public static ManualResetEvent allDone = new ManualResetEvent(false); public ManualResetEvent allDone = new ManualResetEvent(false); private int nPort = 10000; Thread mythread; Socket listener; bool listenerRun=true; public AsynchronousSocketListener(String port) { nPort = int.Parse(port); } private void StartListening() { // Data buffer for incoming data. byte[] bytes = new Byte[1024]; // Establish the local endpoint for the socket. // The DNS name of the computer // running the listener is "host.contoso.com". IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, nPort); // Create a TCP/IP socket. listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Bind the socket to the local endpoint and listen for incoming connections. try { listener.Bind(localEndPoint); listener.Listen(100); while (listenerRun) { // Set the event to nonsignaled state. allDone.Reset(); // Start an asynchronous socket to listen for connections. Console.WriteLine("Waiting for a connection..."); listener.BeginAccept( new AsyncCallback(AcceptCallback), listener); // Wait until a connection is made before continuing. allDone.WaitOne(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("\nPress ENTER to continue..."); Console.Read(); } //public static void AcceptCallback(IAsyncResult ar) public void AcceptCallback(IAsyncResult ar) { // Signal the main thread to continue. allDone.Set(); // Get the socket that handles the client request. Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Create the state object. StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } //public static void ReadCallback(IAsyncResult ar) public void ReadCallback(IAsyncResult ar) { String content = String.Empty; // Retrieve the state object and the handler socket // from the asynchronous state object. StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; // Read data from the client socket. int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { // There might be more data, so store the data received so far. state.sb.Append(Encoding.ASCII.GetString( state.buffer, 0, bytesRead)); // Check for end-of-file tag. If it is not there, read // more data. content = state.sb.ToString(); if (content.IndexOf("<EOF>") > -1) { EndPoint tempRemoteEP = handler.RemoteEndPoint; IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP; string rempip = tempRemoteIP.Address.ToString(); string remoport = tempRemoteIP.Port.ToString(); OnReceiveCustomEvent(new SocketEventArgs(rempip, remoport, content)); //if (ReceiveCustomEvent!=null) // ReceiveCustomEvent(null,new CustomEventArgs(rempip, content)); Console.WriteLine("Read {0} bytes from socket. \n ip : {1}", content.Length, rempip); // All the data has been read from the // client. Display it on the console. Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content); // Echo the data back to the client. Send(handler, content); } else { // Not all data received. Get more. handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } } } //private static void Send(Socket handler, String data) private void Send(Socket handler, String data) { // Convert the string data to byte data using ASCII encoding. byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device. handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } //private static void SendCallback(IAsyncResult ar) private void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object. Socket handler = (Socket)ar.AsyncState; // Complete sending the data to the remote device. int bytesSent = handler.EndSend(ar); Console.WriteLine("Sent {0} bytes to client.", bytesSent); handler.Shutdown(SocketShutdown.Both); handler.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } public void StartService() { mythread = new Thread(new ThreadStart(StartListening)); mythread.Start(); } public void StopService() { try { listenerRun = false; listener.Close(); mythread.Abort(); mythread = null; System.Console.WriteLine("与客户端断开连接!"); } catch (Exception ex) { System.Console.WriteLine(ex.Message); } } protected virtual void OnReceiveCustomEvent(SocketEventArgs e) { EventHandler<SocketEventArgs> handler = ReceiveCustomEvent; if (handler != null) { //handler(this, e); handler(null, e); } } //public static int Main(String[] args) //{ // StartListening(); // return 0; //} } }
?事件参数类
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace yokohama.socket { public class SocketEventArgs : EventArgs { private string message; public string Message { get { return message; } set { message = value; } } private string ip; public string Ip { get { return ip; } set { ip = value; } } private string port; public string Port { get { return port; } set { port = value; } } public SocketEventArgs(string socketIp, string socketPort, string socketMessage) { ip = socketIp; port = socketPort; message = socketMessage; } } }
?状态类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; namespace yokohama.socket { // State object for receiving data from remote device. class StateObject { // Client socket. public Socket workSocket = null; // Size of receive buffer. public const int BufferSize = 256; // Receive buffer. public byte[] buffer = new byte[BufferSize]; // Received data string. public StringBuilder sb = new StringBuilder(); } }?
为了超了2W字,再来调整,我还是先发一次吧,需要继续看的,请看下一篇