以用socket通讯发送和接受坐标点对(x,y)为例:
C#异步socket通讯--服务器端
在异步socket服务端中,建立连接、接收数据、发送数据都要设置回调函数。在每次监听连接、接收和发送数据是都需要调用BeginXXX的过程。特别需要注意的是,在接收数据时,若要不停的监听数据,每次收到数据后要立刻调用BeginReceive函数(见代码中的ReadCallback函数);每次接收的实际数据可能小于设置的缓冲区大小(数据包小于缓冲区长度时)。
View Code
public class Channel
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
static Channel instance = null;
private bool isConnected;
private byte[] buf;
float x, y;
Socket socket, listener;
public static Channel Instance()
{
if (instance == null)
{
instance = new Channel();
}
return instance;
}
private Channel()
{
buf = new byte[1024];
isConnected = false;
x = 0;
y = 0;
}
public bool startServer(string strIP,int portNum)
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化socket
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化socket
IPAddress[] ipAddr = Dns.GetHostAddresses(strIP);
IPAddress ip = ipAddr[0];
IPEndPoint hostEP = new IPEndPoint(ip, portNum);
try
{
listener.Bind(hostEP);
listener.Listen(100);
// Set the event to nonsignaled state.
allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString());
return false;
}
return true;
}
public void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
listener = (Socket)ar.AsyncState;
socket= listener.EndAccept(ar);
//读取客户端内容
Thread t = new Thread(new ThreadStart(threadrecv));
t.Start();
socket.BeginReceive(buf, 0, 1024, 0,new AsyncCallback(ReadCallback),null);
isConnected = true;
}
private void threadrecv()
{
socket.BeginReceive(buf, 0, 1024, 0, new AsyncCallback(ReadCallback), socket);
}
public void ReadCallback(IAsyncResult ar)
{
int byteread = socket.EndReceive(ar);
x = BitConverter.ToSingle(buf, 12);
y = BitConverter.ToSingle(buf, 16);
socket.BeginReceive(buf, 0, 1024, 0, new AsyncCallback(ReadCallback), socket);
}
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);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
public bool getPoint(ref float x,ref float y)
{
x = this.x;
y=this.y;
return true;
}
public bool close()
{
try
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
listener.Close();
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
return true;
}
public bool sendPoint(float x, float y)
{
if(isConnected==false)
{
return false;
}
float flag = 0;
byte[] bf = BitConverter.GetBytes(flag);
byte[] bx = BitConverter.GetBytes(x);
byte[] by = BitConverter.GetBytes(y);
byte[] buffer = new byte[50];
bf.CopyTo(buffer, 0);
bx.CopyTo(buffer, 4);
by.CopyTo(buffer, 8);
bf.CopyTo(buffer, 12);
bf.CopyTo(buffer, 16);
socket.BeginSend(buffer,0,20,0,new AsyncCallback(SendCallback), socket);
return true;
}
}
C#同步socket通讯
同步通讯比较简单,见代码(服务器端与客户端代码差别不大)
View Code
public class Channel
{
static Channel instance = null;
private bool isConnected;
private byte[] buf;
private NetworkStream ns;
Socket socket;
public static Channel Instance()
{
if (instance == null)
{
instance = new Channel();
}
return instance;
}
private Channel()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化socket
buf = new byte[1024];
isConnected = false;
}
public bool connect(string strIP,int portNum,int readTimeOut)
{
IPAddress [] ipAddr=Dns.GetHostAddresses(strIP);
IPAddress ip=ipAddr[0];
IPEndPoint hostEP=new IPEndPoint(ip,portNum);
isConnected = true;
try
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化socket
s.Bind(hostEP);
s.Listen(0);
socket = s.Accept();
//尝试连接 客户端时
//socket=socket.Connect(hostEP);
}
catch(Exception se)
{
MessageBox.Show("连接错误"+se.Message,"提示信息",
MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
isConnected = false;
return false;
}
ns = new NetworkStream(socket);
if (readTimeOut < 0)
readTimeOut = 0;
ns.ReadTimeout = readTimeOut;
return isConnected;
}
public bool getPoint(ref float x,ref float y)
{
if(isConnected==false)
{
return false;
}
try
{
if (ns.DataAvailable)
{
while (ns.DataAvailable)
{
ns.Read(buf, 0, 20);
}
}
else
{
ns.Read(buf, 0, 20);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
x=BitConverter.ToSingle(buf, 12);
y = BitConverter.ToSingle(buf, 16);
return true;
}
public bool close()
{
try
{
if (ns != null)
{
ns.Close();
}
if (socket != null)
{
socket.Close();
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
return true;
}
public bool sendPoint(float x, float y)
{
if(isConnected==false)
{
return false;
}
float flag = 0;
byte[] bf = BitConverter.GetBytes(flag);
byte[] bx = BitConverter.GetBytes(x);
byte[] by = BitConverter.GetBytes(y);
bf.CopyTo(buf, 0);
bx.CopyTo(buf, 4);
by.CopyTo(buf, 8);
bf.CopyTo(buf, 12);
bf.CopyTo(buf, 16);
try
{
ns.Write(buf, 0, 20);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
ns.Flush();
return true;
}
}
总结:在实时性要求比较高的系统中,用异步通讯是较好的选择;同步通讯由于发送和接收都是阻塞调用的,当需要接收数据而端口没有数据过来的时候,需要等待较长的时间影响系统性能,用多线程的方法对数据进行接收和发送也许是一个不错的选择,有待试验(例如在连接建立的同时开一个线程处理接收数据的函数)。