???? 最近因项目需要,需要用到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字,再来调整,我还是先发一次吧,需要继续看的,请看下一篇