You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
9.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Configuration;
namespace Mesnac.Communication
{
public class SocketClient : IDisposable
{
private static SocketClient instance = null;
/// <summary>
/// 客户端连接Socket
/// </summary>
private Socket clientSocket;
/// <summary>
/// 连接状态
/// </summary>
private Boolean connected = false;
/// <summary>
/// 连接点
/// </summary>
private IPEndPoint hostEndPoint;
/// <summary>
/// 连接信号量
/// </summary>
private static AutoResetEvent autoConnectEvent = new AutoResetEvent(false);
/// <summary>
/// 接受到数据时的委托
/// </summary>
/// <param name="info"></param>
public delegate void ReceiveMsgHandler(string info);
/// <summary>
/// 接收到数据时调用的事件
/// </summary>
public event ReceiveMsgHandler OnMsgReceived;
/// <summary>
/// 开始监听数据的委托
/// </summary>
public delegate void StartListenHandler();
/// <summary>
/// 开始监听数据的事件
/// </summary>
public event StartListenHandler StartListenThread;
/// <summary>
/// 发送信息完成的委托
/// </summary>
/// <param name="successorfalse"></param>
public delegate void SendCompleted(bool successorfalse);
/// <summary>
/// 发送信息完成的事件
/// </summary>
public event SendCompleted OnSended;
/// <summary>
/// 监听接收的SocketAsyncEventArgs
/// </summary>
private SocketAsyncEventArgs listenerSocketAsyncEventArgs;
/// <summary>
/// 监听线程
/// </summary>
Thread receiveThread = null;
public static string hostName;
public static int port;
/// <summary>
/// TCP通信服务实例
/// </summary>
public static SocketClient Instance
{
get
{
if (instance == null)
{
instance = new SocketClient();
}
return instance;
}
}
/// <summary>
/// 启动服务
/// </summary>
public static void StartService()
{
if (instance == null)
{
instance = new SocketClient();
}
}
/// <summary>
/// 初始化客户端
/// </summary>
/// <param name="hostName">服务端地址{IP地址}</param>
/// <param name="port">端口号</param>
public SocketClient()//String hostName, Int32 port
{
object listenServerIP = ConfigurationManager.AppSettings["ListenServerIP"];
string oport = ConfigurationManager.AppSettings["Port"].ToString();
string hostName = listenServerIP.ToString();
int port = 0;
int.TryParse(oport, out port);
IPHostEntry host = Dns.GetHostEntry(hostName);
IPAddress[] addressList = host.AddressList;
this.hostEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port);
this.clientSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
//Connect();
}
/// <summary>
/// 连接服务端
/// </summary>
public bool Connect()
{
SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
connectArgs.UserToken = this.clientSocket;
connectArgs.RemoteEndPoint = this.hostEndPoint;
connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);
clientSocket.ConnectAsync(connectArgs);
//等待连接结果
autoConnectEvent.WaitOne();
SocketError errorCode = connectArgs.SocketError;
if (errorCode == SocketError.Success)
{
listenerSocketAsyncEventArgs = new SocketAsyncEventArgs();
byte[] receiveBuffer = new byte[32768];
listenerSocketAsyncEventArgs.UserToken = clientSocket;
listenerSocketAsyncEventArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
listenerSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
StartListenThread += new SocketClient.StartListenHandler(listener_StartListenThread);
StartListenThread();
return true;
}
else
//throw new SocketException((Int32)errorCode);
return false;
}
private void listener_StartListenThread()
{
ICSharpCode.Core.LoggingService.Debug("开始侦听...");
//receiveThread = new Thread(new ThreadStart(Listen));
Listen();
}
/// <summary>
/// 开始监听线程的入口函数
/// </summary>
public void Listen()
{
(listenerSocketAsyncEventArgs.UserToken as Socket).ReceiveAsync(listenerSocketAsyncEventArgs);
}
/// <summary>
/// 停止监听线程
/// </summary>
public void StopListenThread()
{
//receiveThread.Abort();
if (clientSocket != null)
clientSocket.Close();
clientSocket = null;
Dispose();
}
/// <summary>
/// 发送信息
/// </summary>
/// <param name="message"></param>
public void Send(String message)
{
if (this.connected)
{
message = String.Format("[length={0}]{1}", message.Length, message);
Byte[] sendBuffer = Encoding.Unicode.GetBytes(message);
SocketAsyncEventArgs senderSocketAsyncEventArgs = new SocketAsyncEventArgs();
senderSocketAsyncEventArgs.UserToken = this.clientSocket;
senderSocketAsyncEventArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
senderSocketAsyncEventArgs.RemoteEndPoint = this.hostEndPoint;
senderSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);
clientSocket.SendAsync(senderSocketAsyncEventArgs);
}
else
{
throw new SocketException((Int32)SocketError.NotConnected);
}
}
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
clientSocket.Disconnect(false);
}
/// <summary>
/// 连接的完成方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnConnect(object sender, SocketAsyncEventArgs e)
{
autoConnectEvent.Set();
this.connected = (e.SocketError == SocketError.Success);
}
/// <summary>
/// 接收的完成方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnReceive(object sender, SocketAsyncEventArgs e)
{
string msg = Encoding.Default.GetString(e.Buffer, 0, e.BytesTransferred);
ICSharpCode.Core.LoggingService.Info("接收到数据" + msg);
//Console.WriteLine("接收到数据"+msg);
Listen();
if (OnMsgReceived != null)
OnMsgReceived(msg);
}
/// <summary>
/// 发送的完成方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSend(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
OnSended(true);
}
else
{
OnSended(false);
this.ProcessError(e);
}
}
/// <summary>
/// 处理错误
/// </summary>
/// <param name="e"></param>
private void ProcessError(SocketAsyncEventArgs e)
{
Socket s = e.UserToken as Socket;
if (s.Connected)
{
try
{
s.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
//client already closed
}
finally
{
if (s.Connected)
{
s.Close();
}
}
}
throw new SocketException((Int32)e.SocketError);
}
#region IDisposable Members
public void Dispose()
{
autoConnectEvent.Close();
if (clientSocket != null && this.clientSocket != null)
{
if (this.clientSocket.Connected)
{
this.clientSocket.Close();
}
}
}
#endregion
}
}