C#:簡單的Socket非同步通訊服務
Socket
請參考此連結來獲取對於Socket的認識:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.aspx
目標
1、服務端接收到來自客戶端的訊息
2、服務端間歇性地向客戶端傳送訊息
3、服務端主動向客戶端傳送訊息
思路
通過對Socket的學習後,可以知道:
1、Socket分為面向連線協議(如TCP)和無連線協議(如UDP)
2、Socket通訊分為同步操作模式和非同步操作模式,同步模式在建立連線之前/收到訊息之前會阻塞當前程序,非同步模式不會阻塞當前程序
綜合以上兩點,考慮到體驗,當然是選擇非同步Socket啦,另外,這裡使用的是面向連線的協議,那麼實現思路大致如下:
1、建立Socket物件
2、繫結IP和埠
3、偵聽連線
4、開始一個非同步操作來接收一個接入的連線請求
5、處理接入的請求
6、向客戶端傳送訊息
程式碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.IO;
using Microsoft.Win32;
using System.Threading;
using System.Net;
using System.Net.Sockets;
namespace TSNotifier
{
public partial class TSNotifier : ServiceBase
{
Socket socket;
public TSNotifier()
{
InitializeComponent();
}
/// <summary>
/// 服務啟動
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
//Debugger.Launch();//啟動除錯,生產環境刪掉
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Any, 4530));//偵聽來自任意IP的連線請求
socket.Listen(500);
socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
}
/// <summary>
/// 服務停止
/// </summary>
protected override void OnStop()
{
try
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
catch (Exception ex)
{
}
}
public static void ClientAccepted(IAsyncResult ar)
{
var socket = ar.AsyncState as Socket;
var client = socket.EndAccept(ar);
string clientIp = ((System.Net.IPEndPoint)client.RemoteEndPoint).Address.ToString();
string clientPort = ((System.Net.IPEndPoint)client.RemoteEndPoint).Port.ToString();
client.Send(Encoding.Unicode.GetBytes("Hi " + clientIp + ":" + clientPort + ", I accept you request at " + DateTime.Now.ToString()));
//每隔兩秒鐘給客戶端發一個訊息
var timer = new System.Timers.Timer();
timer.Interval = 2000;
timer.Enabled = true;
timer.Elapsed += (o, a) =>
{
//檢測客戶端Socket的狀態
if (client.Connected)
{
try
{
client.Send(Encoding.Unicode.GetBytes("Server online."));
}
catch (SocketException ex)
{
}
}
else
{
timer.Stop();
timer.Enabled = false;
}
};
timer.Start();
//接收客戶端的訊息
try
{
client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), client);
}
catch (Exception ex)
{
}
//準備接受下一個客戶端請求
socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
}
static byte[] buffer = new byte[1024];
public static void ReceiveMessage(IAsyncResult ar)
{
var socket = ar.AsyncState as Socket;
string clientIp = ((IPEndPoint)socket.RemoteEndPoint).Address.ToString();
string clientPort = ((IPEndPoint)socket.RemoteEndPoint).Port.ToString();
try
{
var length = socket.EndReceive(ar);
var message = Encoding.Unicode.GetString(buffer, 0, length);
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);
}
catch (Exception ex)
{
}
}
}
}
客戶端的實現請參考:http://www.rexcao.net/archives/161