修正一下SocketManager中的SocketServer类
/**
* 作者:王文斌
* 做成日:2008-5-9
* 版本:0.2
* 说明:Socket服务端,接收到的信息放在队列里,开个线程,监听队列信息。
* 目前客户端识别只提供ip识别,可以考虑利用SocketConn保存客户端识别名称
* */
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Collections;
namespace WWBClassLib.SocketManager
{
/// <summary>
/// 连接类
/// </summary>
public class SocketConn
{
/// <summary>
/// 连接对象
/// </summary>
private Socket sock;
/// <summary>
/// 识别名称
/// </summary>
private string name;
/// <summary>
/// 连接对象
/// </summary>
public Socket Sock
{
set { sock = value; }
get { return sock; }
}
/// <summary>
/// 识别名称
/// </summary>
public string Name
{
set { name = value; }
get { return name; }
}
/// <summary>
/// 构造方法 服务端命名
/// </summary>
/// <param name="socket">连接</param>
/// <param name="name">识别名</param>
public SocketConn(Socket socket, string name)
{
sock = socket;
this.name = name;
}
/// <summary>
/// 构造方法,默认识别名为ip
/// </summary>
/// <param name="socket">连接对象</param>
public SocketConn(Socket socket)
{
sock = socket;
this.name = ((IPEndPoint)socket.RemoteEndPoint).Address.ToString();
}
}
/// <summary>
/// SocketConn专用集合类
/// </summary>
public class SocketConList
{
private List<SocketConn> list = new List<SocketConn>();
public void ADD(SocketConn con)
{
list.Add(con);
}
public void Remove(SocketConn con)
{
list.Remove(con);
}
public void Remove(string name)
{
lock (list)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i].Name.Equals(name))
{
list.Remove(list[i]);
}
}
}
}
public void Remove(Socket sock)
{
lock (list)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i].Sock.Equals(sock))
{
list.Remove(list[i]);
}
}
}
}
public void Clear()
{
list.Clear();
}
public void RemoveAt(int i)
{
list.RemoveAt(i);
}
public SocketConn Find(string name)
{
lock (list)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i].Name.Equals(name))
{
return list[i];
}
}
}
return null;
}
public List<SocketConn> List
{
get { return list; }
}
}
/// <summary>
/// 简单套接字服务端
/// </summary>
public class SocketServer2
{
/// <summary>
/// 服务器IP
/// </summary>
private IPAddress serverIP;
/// <summary>
/// 完整终端地址包含端口
/// </summary>
private IPEndPoint serverFullAddr;
/// <summary>
/// 服务器端监听用Socket对象
/// </summary>
private Socket sock;
/// <summary>
/// 服务器监听线程
/// </summary>
private System.Timers.Timer myTimer;
/// <summary>
/// 保存链接用集合
/// </summary>
//private List<Socket> alSock;//当建立了多个连接时用于保存连接
private SocketConList socklist;
/// <summary>
/// 端口号,默认15693
/// </summary>
private int portNo = 15693;
/// <summary>
/// 储存接受到的消息队列
/// </summary>
public Queue commands = new Queue();
/// <summary>
/// 构造函数 端口默认15693
/// </summary>
/// <param name="ServerIP">服务器ip</param>
/// <param name="commands">消息队列</param>
public SocketServer2(string ServerIP, Queue commands)
{
serverIP = IPAddress.Parse(ServerIP);
this.commands = commands;
}
/// <summary>
/// 构造函数,设定端口
/// </summary>
/// <param name="ServerIP">服务器ip</param>
/// <param name="portNo">端口号</param>
/// <param name="commands">消息队列</param>
public SocketServer2(string ServerIP, int portNo, Queue commands)
{
serverIP = IPAddress.Parse(ServerIP);
this.portNo = portNo;
this.commands = commands;
}
/// <summary>
/// 获取连接IP集合
/// </summary>
/// <returns>IP集合</returns>
public List<string> GetListIPs()
{
List<string> list = new List<string>();
lock (socklist)
{
for (int i = 0; i < socklist.List.Count; i++)
{
list.Add(((IPEndPoint)socklist.List[i].Sock.RemoteEndPoint).Address.ToString());
}
}
return list;
}
/// <summary>
/// 启动监听,创建链接
/// </summary>
/// <returns>创建结果</returns>
public bool StartLinsten()
{
//取得完整地址
serverFullAddr = new IPEndPoint(serverIP, portNo);//取端口号
try
{
//构造Socket对象,套接字类型为“流套接字”,指定五元组中的协议元
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//指定五元组中的本地二元,即本地主机地址和端口号
sock.Bind(serverFullAddr);
//监听是否有连接传入,指定挂起的连接队列的最大值为20
sock.Listen(20);
}
catch
{
return false;
}
//初始化存储链接集合
socklist = new SocketConList();
//构造定时器,时间间隙为1秒,即每隔一秒执行一次accept()方法,以获取连接请求队列中//第一个挂起的连接请求
myTimer = new System.Timers.Timer(1000);
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
myTimer.Enabled = true;
return true;
}
/// <summary>
/// 监听线程
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//暂时中断线程
myTimer.Enabled = false;
//执行accept(),当挂起队列为空时将阻塞本线程,同时由于上一语句,定时器将停止,直//至有连接传入
Socket acceptSock = sock.Accept();
//将accept()产生的Socket对象存入ArrayList
SocketConn conn = new SocketConn(acceptSock);
socklist.ADD(conn);
// 构造Threading.Timer对象,这将导致程序另启线程。线程将执行回调函数,该委托限制//函数参数须为object型。Threading.Timer构造器的第二个参数即传入回调函数的参数;第//三个参数指定调用回调函数之前的延时,取0则立即启动;最后一个参数指定调用回调函数//的时间间隔,取0则只执行一次。
System.Threading.Timer ti = new System.Threading.Timer(new TimerCallback(ReceiveMsg), acceptSock, 0, 0);
//重新启用线程
myTimer.Enabled = true;
}
/// <summary>
/// 接受信息方法
/// </summary>
/// <param name="obj"></param>
private void ReceiveMsg(object obj)
{
//取得链接对象
Socket acceptSock = (Socket)obj;
try
{
while (true)
{
//判断链接,未连接的移除
if (!acceptSock.Connected)
{
socklist.Remove(acceptSock);
acceptSock.Close();
}
//定义接收字节流
byte[] byteArray = new byte[1000];
byte[] comArray = new byte[1000];
//接受数据
acceptSock.Receive(byteArray);//接收数据
//判断数据有效性
if (!BitConverter.ToString(byteArray).Equals(BitConverter.ToString(comArray)))
{
//添加至消息队列
commands.Enqueue(byteArray);
}
}
}
catch (Exception ex)
{
//接收消息失败,关闭连接,移除链接
acceptSock.Close();
socklist.Remove(acceptSock);
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="message">消息字节流</param>
/// <param name="ip">对象ip</param>
/// <returns>结果</returns>
public bool SendMessage(byte[] message, string ip)
{
//定义对象
Socket sc = null;
try
{
//多线程访问集合对象,遍历时需要锁定,避免便利同时数组变化错误
SocketConn conn = socklist.Find(ip);
sc = conn.Sock;
//判断存在相应对象
if (sc != null)
{
//发送数据
sc.Send(message);
return true;
}
return false;
}
catch (Exception ex)
{
//发送错误,移除链接
if (sc != null)
{
sc.Close();
socklist.Remove(sc);
}
return false;
}
}
}
/// <summary>
/// 简单套接字服务端
/// </summary>
public class SocketServer
{
/// <summary>
/// 服务器IP
/// </summary>
private IPAddress serverIP;
/// <summary>
/// 完整终端地址包含端口
/// </summary>
private IPEndPoint serverFullAddr;
/// <summary>
/// 服务器端监听用Socket对象
/// </summary>
private Socket sock;
/// <summary>
/// 服务器监听线程
/// </summary>
private System.Timers.Timer myTimer;
/// <summary>
/// 保存链接用集合
/// </summary>
private List<Socket> alSock;//当建立了多个连接时用于保存连接
/// <summary>
/// 端口号,默认15693
/// </summary>
private int portNo = 15693;
/// <summary>
/// 储存接受到的消息队列
/// </summary>
public Queue commands = new Queue();
/// <summary>
/// 构造函数 端口默认15693
/// </summary>
/// <param name="ServerIP">服务器ip</param>
/// <param name="commands">消息队列</param>
public SocketServer(string ServerIP,Queue commands)
{
serverIP = IPAddress.Parse(ServerIP);
this.commands = commands;
}
/// <summary>
/// 构造函数,设定端口
/// </summary>
/// <param name="ServerIP">服务器ip</param>
/// <param name="portNo">端口号</param>
/// <param name="commands">消息队列</param>
public SocketServer(string ServerIP, int portNo, Queue commands)
{
serverIP = IPAddress.Parse(ServerIP);
this.portNo = portNo;
this.commands = commands;
}
/// <summary>
/// 获取连接IP集合
/// </summary>
/// <returns>IP集合</returns>
public List<string> GetListIPs()
{
List<string> list = new List<string>();
lock (alSock)
{
for (int i = 0; i < alSock.Count; i++)
{
list.Add(((IPEndPoint)alSock[i].RemoteEndPoint).Address.ToString());
}
}
return list;
}
/// <summary>
/// 启动监听,创建链接
/// </summary>
/// <returns>创建结果</returns>
public bool StartLinsten()
{
//取得完整地址
serverFullAddr = new IPEndPoint(serverIP, portNo);//取端口号
try
{
//构造Socket对象,套接字类型为“流套接字”,指定五元组中的协议元
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//指定五元组中的本地二元,即本地主机地址和端口号
sock.Bind(serverFullAddr);
//监听是否有连接传入,指定挂起的连接队列的最大值为20
sock.Listen(20);
}
catch
{
return false;
}
//初始化存储链接集合
alSock = new List<Socket>();
//构造定时器,时间间隙为1秒,即每隔一秒执行一次accept()方法,以获取连接请求队列中//第一个挂起的连接请求
myTimer = new System.Timers.Timer(1000);
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
myTimer.Enabled = true;
return true;
}
/// <summary>
/// 监听线程
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//暂时中断线程
myTimer.Enabled = false;
//执行accept(),当挂起队列为空时将阻塞本线程,同时由于上一语句,定时器将停止,直//至有连接传入
Socket acceptSock = sock.Accept();
//将accept()产生的Socket对象存入ArrayList
alSock.Add(acceptSock);
// 构造Threading.Timer对象,这将导致程序另启线程。线程将执行回调函数,该委托限制//函数参数须为object型。Threading.Timer构造器的第二个参数即传入回调函数的参数;第//三个参数指定调用回调函数之前的延时,取0则立即启动;最后一个参数指定调用回调函数//的时间间隔,取0则只执行一次。
System.Threading.Timer ti = new System.Threading.Timer(new TimerCallback(ReceiveMsg), acceptSock, 0, 0);
//重新启用线程
myTimer.Enabled = true;
}
/// <summary>
/// 接受信息方法
/// </summary>
/// <param name="obj"></param>
private void ReceiveMsg(object obj)
{
//取得链接对象
Socket acceptSock = (Socket)obj;
try
{
while (true)
{
//判断链接,未连接的移除
if (!acceptSock.Connected)
{
alSock.Remove(acceptSock);
acceptSock.Close();
}
//定义接收字节流
byte[] byteArray = new byte[1000];
byte[] comArray = new byte[1000];
//接受数据
acceptSock.Receive(byteArray);//接收数据
//判断数据有效性
if (!BitConverter.ToString(byteArray).Equals(BitConverter.ToString(comArray)))
{
//添加至消息队列
commands.Enqueue(byteArray);
}
}
}
catch (Exception ex)
{
//接收消息失败,关闭连接,移除链接
acceptSock.Close();
alSock.Remove(acceptSock);
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="message">消息字节流</param>
/// <param name="ip">对象ip</param>
/// <returns>结果</returns>
public bool SendMessage(byte[] message,string ip)
{
//定义对象
Socket sc = null;
try
{
//多线程访问集合对象,遍历时需要锁定,避免便利同时数组变化错误
lock (alSock)
{
//通过ip选择链接对象
for (int i = 0; i < alSock.Count; i++)
{
if (((IPEndPoint)alSock[i].RemoteEndPoint).Address.ToString().Equals(ip))
{
sc = alSock[i];
break;
}
}
}
//判断存在相应对象
if (sc != null)
{
//发送数据
sc.Send(message);
return true;
}
return false;
}
catch (Exception ex)
{
//发送错误,移除链接
if (sc != null)
{
sc.Close();
alSock.Remove(sc);
}
return false;
}
}
}
}