C#同步异步socket通讯编程

以用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 ;
}
}

   总结:在实时性要求比较高的系统中,用异步通讯是较好的选择;同步通讯由于发送和接收都是阻塞调用的,当需要接收数据而端口没有数据过来的时候,需要等待较长的时间影响系统性能,用多线程的方法对数据进行接收和发送也许是一个不错的选择,有待试验(例如在连接建立的同时开一个线程处理接收数据的函数)。

你可能感兴趣的:(socket)