以用socket通讯发送和接受坐标点对(x,y)为例:
C#异步socket通讯--服务器端
在异步socket服务端中,建立连接、接收数据、发送数据都要设置回调函数。在每次监听连接、接收和发送数据是都需要调用BeginXXX的过程。特别需要注意的是,在接收数据时,若要不停的监听数据,每次收到数据后要立刻调用BeginReceive函数(见代码中的ReadCallback函数);每次接收的实际数据可能小于设置的缓冲区大小(数据包小于缓冲区长度时)。
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通讯
同步通讯比较简单,见代码(服务器端与客户端代码差别不大)
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 ;
}
}
总结:在实时性要求比较高的系统中,用异步通讯是较好的选择;同步通讯由于发送和接收都是阻塞调用的,当需要接收数据而端口没有数据过来的时候,需要等待较长的时间影响系统性能,用多线程的方法对数据进行接收和发送也许是一个不错的选择,有待试验(例如在连接建立的同时开一个线程处理接收数据的函数)。