using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using HPSocketCS;
using System.Threading;
namespace SSLServerNS
{
public enum AppState
{
Starting, Started, Stoping, Stoped, Error
}
public partial class frmServer : Form
{
private AppState appState = AppState.Stoped;
private delegate void ShowMsg(string msg);
private ShowMsg AddMsgDelegate;
HPSocketCS.TcpServer server = new HPSocketCS.TcpServer();
private static string title = "Echo-PFM Server [ 'C' - clear list box, 'R' - reset statics data ]";
private long totalReceived = 0;
private long totalSent = 0;
private long clientCount = 0;
public frmServer()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
this.Text = title;
// 本机测试没必要改地址,有需求请注释或删除
this.txtIpAddress.ReadOnly = true;
// 加个委托显示msg,因为on系列都是在工作线程中调用的,ui不允许直接操作
AddMsgDelegate = new ShowMsg(AddMsg);
// 设置服务器事件
server.OnPrepareListen += new TcpServerEvent.OnPrepareListenEventHandler(OnPrepareListen);
server.OnAccept += new TcpServerEvent.OnAcceptEventHandler(OnAccept);
server.OnSend += new TcpServerEvent.OnSendEventHandler(OnSend);
server.OnReceive += new TcpServerEvent.OnReceiveEventHandler(OnReceive);
server.OnClose += new TcpServerEvent.OnCloseEventHandler(OnClose);
server.OnShutdown += new TcpServerEvent.OnShutdownEventHandler(OnShutdown);
SetAppState(AppState.Stoped);
}
catch (Exception ex)
{
SetAppState(AppState.Error);
AddMsg(ex.Message);
}
}
private void btnStart_Click(object sender, EventArgs e)
{
try
{
String ip = this.txtIpAddress.Text.Trim();
ushort port = ushort.Parse(this.txtPort.Text.Trim());
// 写在这个位置是上面可能会异常
SetAppState(AppState.Starting);
Reset();
server.IpAddress = ip;
server.Port = port;
// 启动服务
if (server.Start())
{
this.Text = string.Format("{2} - ({0}:{1})", ip, port, title);
SetAppState(AppState.Started);
AddMsg(string.Format("$Server Start OK -> ({0}:{1})", ip, port));
}
else
{
SetAppState(AppState.Stoped);
throw new Exception(string.Format("$Server Start Error -> {0}({1})", server.ErrorMessage, server.ErrorCode));
}
}
catch (Exception ex)
{
AddMsg(ex.Message);
}
}
private void btnStop_Click(object sender, EventArgs e)
{
SetAppState(AppState.Stoping);
// 停止服务
AddMsg("$Server Stop");
if (server.Stop())
{
this.Text = title;
SetAppState(AppState.Stoped);
}
else
{
AddMsg(string.Format("$Stop Error -> {0}({1})", server.ErrorMessage, server.ErrorCode));
}
}
private void btnDisconn_Click(object sender, EventArgs e)
{
try
{
IntPtr connId = (IntPtr)Convert.ToUInt32(this.txtDisConn.Text.Trim());
// 断开指定客户
if (server.Disconnect(connId, true))
{
AddMsg(string.Format("$({0}) Disconnect OK", connId));
}
else
{
throw new Exception(string.Format("Disconnect({0}) Error", connId));
}
}
catch (Exception ex)
{
AddMsg(ex.Message);
}
}
void Reset(bool isSetClientCount = true)
{
if (isSetClientCount)
{
clientCount = 0;
}
totalReceived = 0;
totalSent = 0;
}
HandleResult OnPrepareListen(IntPtr soListen)
{
// 监听事件到达了,一般没什么用吧?
return HandleResult.Ok;
}
HandleResult OnAccept(IntPtr connId, IntPtr pClient)
{
// 客户进入了
if (clientCount == 0)
{
lock (title)
{
if (clientCount == 0)
{
Reset(false);
}
}
}
Interlocked.Increment(ref clientCount);
// 获取客户端ip和端口
string ip = string.Empty;
ushort port = 0;
if (server.GetRemoteAddress(connId, ref ip, ref port))
{
AddMsg(string.Format(" > [{0},OnAccept] -> PASS({1}:{2})", connId, ip.ToString(), port));
}
else
{
AddMsg(string.Format(" > [{0},OnAccept] -> Server_GetClientAddress() Error", connId));
}
return HandleResult.Ok;
}
HandleResult OnSend(IntPtr connId, byte[] bytes)
{
// 服务器发数据了
Interlocked.Add(ref totalSent, bytes.Length);
//AddMsg(string.Format(" > [{0},OnSend] -> ({1} bytes)", connId, length));
return HandleResult.Ok;
}
HandleResult OnReceive(IntPtr connId, byte[] bytes)
{
// 数据到达了
Interlocked.Add(ref totalReceived, bytes.Length);
if (server.Send(connId, bytes, bytes.Length))
{
return HandleResult.Ok;
}
return HandleResult.Error;
}
HandleResult OnClose(IntPtr connId, SocketOperation enOperation, int errorCode)
{
if(errorCode == 0)
AddMsg(string.Format(" > [{0},OnClose]", connId));
else
AddMsg(string.Format(" > [{0},OnError] -> OP:{1},CODE:{2}", connId, enOperation, errorCode));
Calculate();
return HandleResult.Ok;
}
HandleResult OnShutdown()
{
// 服务关闭了
AddMsg(" > [OnShutdown]");
return HandleResult.Ok;
}
void Calculate()
{
if(clientCount > 0)
{
lock(title)
{
if(clientCount > 0)
{
Interlocked.Decrement(ref clientCount);
if(clientCount == 0)
{
//::WaitWithMessageLoop(600L);
Thread tmpThread = new Thread(ShowTotalMsg);
tmpThread.Start();
}
}
}
}
}
void ShowTotalMsg()
{
Thread.Sleep(600);
AddMsg(string.Format(" *** Summary: send - {0}, recv - {1}", totalSent, totalReceived));
}
///
/// 设置程序状态
///
///
void SetAppState(AppState state)
{
appState = state;
this.btnStart.Enabled = (appState == AppState.Stoped);
this.btnStop.Enabled = (appState == AppState.Started);
this.txtIpAddress.Enabled = (appState == AppState.Stoped);
this.txtPort.Enabled = (appState == AppState.Stoped);
this.txtDisConn.Enabled = (appState == AppState.Started);
this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0);
}
///
/// 往listbox加一条项目
///
///
void AddMsg(string msg)
{
if (this.lbxMsg.InvokeRequired)
{
// 很帅的调自己
this.lbxMsg.Invoke(AddMsgDelegate, msg);
}
else
{
if (this.lbxMsg.Items.Count > 100)
{
this.lbxMsg.Items.RemoveAt(0);
}
this.lbxMsg.Items.Add(msg);
this.lbxMsg.TopIndex = this.lbxMsg.Items.Count - (int)(this.lbxMsg.Height / this.lbxMsg.ItemHeight);
}
}
private void txtDisConn_TextChanged(object sender, EventArgs e)
{
// CONNID框被改变事件
this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0);
}
private void lbxMsg_KeyPress(object sender, KeyPressEventArgs e)
{
// 清理listbox
if (e.KeyChar == 'c' || e.KeyChar == 'C')
{
this.lbxMsg.Items.Clear();
}
else if (e.KeyChar == 'r' || e.KeyChar == 'R')
{
Reset();
AddMsg(string.Format(" *** Reset Statics: CC - {0}, TS - {1}, TR - {2}", clientCount, totalSent, totalReceived));
}
}
private void frmServer_FormClosed(object sender, FormClosedEventArgs e)
{
server.Destroy();
}
}
[StructLayout(LayoutKind.Sequential)]
public class ClientInfo
{
public uint ConnId { get; set; }
public string IpAddress { get; set; }
public ushort Port { get; set; }
}
}