自己封装的多线程通讯类

自己封装的多线程通讯类
使用byte[]传输,可以传输序列化对象等,实现服务器与多个客户端的通信。

服务端:

/**
 * 作者:王文斌
 * 做成日:2008-5-9
 * 版本:0.1
 * 说明: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  SocketModule.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>
    
/// 服务器监听类
    
/// </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>();
            
foreach (Socket s in alSock)
            
{
                list.Add(((IPEndPoint)s.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, 00);

            
//重新启用线程
            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);
                    }


                    
//if (!byteArray.Equals(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
            
{
                
//通过ip选择链接对象
                foreach (Socket s in alSock)
                
{
                    
if (((IPEndPoint)s.RemoteEndPoint).Address.ToString().Equals(ip))
                    
{
                        sc 
= s;
                        
break;
                    }

                }

                
                
//判断存在相应对象
                if (sc != null)
                
{
                    
//发送数据
                    sc.Send(message);
                    
return true;
                }

                
return false;

            }


            
catch (Exception ex)
            
{
                
//发送错误,移除链接
                if (sc != null)
                
{

                    sc.Close();
                    alSock.Remove(sc);

                }


                
return false;

            }

        }

    }

}

 

客户端:

 

/**
 * 作者:王文斌
 * 做成日:2008-5-9
 * 版本:0.1
 * 说明:Socket客户端,接收到的信息放在队列里,客户端需要接收的话,开个线程,监听队列信息即可
 * 
*/

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  SocketModule.SocketManager
{
    
public class SocketClient
    
{
        
/// <summary>
        
/// 服务器IP
        
/// </summary>

        private IPAddress serverIP;

        
/// <summary>
        
/// 完整终端地址包含端口
        
/// </summary>

        private IPEndPoint serverFullAddr;

        
/// <summary>
        
/// 连接用Socket对象
        
/// </summary>

        private Socket sock;

        
/// <summary>
        
/// 端口号,默认15693
        
/// </summary>

        private int portNo = 15693;

        
/// <summary>
        
/// 储存接受到的消息队列
        
/// </summary>

        public Queue commands = new Queue();

        
public string Status
        
{
            
get {
                
if (sock == null)
                    
return "未连接";
                
else if (!sock.Connected)
                
{
                    
return "连接关闭";
                }

                
else
                
{
                    
return "已连接";
                }


            }

        }

        
/// <summary>
        
/// 构造函数,取得服务器ip,默认端口15693
        
/// </summary>
        
/// <param name="ip">服务器ip</param>

        public SocketClient(string ip)
        
{
            serverIP 
= IPAddress.Parse(ip);
        }


        
/// <summary>
        
/// 构造函数,获得ip与端口
        
/// </summary>
        
/// <param name="ip">服务端ip</param>
        
/// <param name="portNo">端口</param>

        public SocketClient(string ip,int portNo)
        
{
            
//设置服务器ip
            serverIP = IPAddress.Parse(ip);

            
//设置端口号
            this.portNo = portNo;
        }


        
/// <summary>
        
/// 建立与服务器连接
        
/// </summary>
        
/// <returns>结果</returns>

        public bool CreatConnection()
        
{
            
try
            
{
                
//服务器完整地址
                serverFullAddr = new IPEndPoint(serverIP, portNo);

                
//创建连接对象
                sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                
//建立连接
                sock.Connect(serverFullAddr);//建立与远程主机的连接

                
//启动新线程用于接收数据

                Thread t 
= new Thread(new ThreadStart(ReceiveMsg));

                t.Name 
= "Receive Message";

                
//一个线程或者是后台线程或者是前台线程。后台线程与前台线程类似,区别是后台线//程不会防止进程终止。一旦属于某一进程的所有前台线程都终止,公共语言运行库就//会通过对任何仍然处于活动状态的后台线程调用 Abort 来结束该进程。

                t.IsBackground 
= true;

                t.Start();
                
return true;
            }


            
catch (Exception ex)
            
{

                
return false;

            }

        }


        
/// <summary>
        
/// 接收消息
        
/// </summary>

        private void ReceiveMsg()
        
{

            
try
            
{

                
while (true)
                
{
                    
//定义byte流
                    byte[] byteRec = new byte[1000];

                    
//接受信息
                    this.sock.Receive(byteRec);

                    commands.Enqueue(byteRec);
                    

                }


            }


            
catch (Exception ex)
            
{
                
//关闭连接
                sock.Close();
            }


        }


        
/// <summary>
        
/// 发送信息
        
/// </summary>
        
/// <param name="Message">消息字节流</param>
        
/// <returns>结果</returns>

        public bool SendMessage(byte[] Message)
        
{
            
try
            
{
                
//发送消息
                this.sock.Send(Message);
                
return true;
            }


            
catch
            
{

                
return false;

            }

        }


        
/// <summary>
        
/// 中断连接
        
/// </summary>
        
/// <returns>结果</returns>

        public bool ShutDown()
        
{
            
try
            
{
                
//中断连接
                this.sock.Shutdown(SocketShutdown.Receive);

                
//关闭
                this.sock.Close();
                
return true;
            }

            
catch
            
{
                
return false;
            }

        }

    }

}

 

工具类:

 

/**
 * 作者:王文斌
 * 做成日:2008-5-9
 * 版本:0.1
 * 说明:网络传输用帮助类
 * 
*/

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.IO;
using  System.Runtime.Serialization;
using  System.Runtime.Serialization.Formatters.Binary;

namespace  SocketModule.SocketManager
{
    
/// <summary>
    
/// 工具类,提供通用处理方法
    
/// </summary>

    public class Util
    
{
        
/// <summary>
        
/// 将对象序列化为byte[] , 对象必须声明序列化
        
/// </summary>
        
/// <param name="obj">要序列化的对象</param>
        
/// <returns>byte[]</returns>

        public static byte[] SerialObjToByte(object obj)
        
{
            
//内存流
            MemoryStream stream = new MemoryStream();

            
//序列化格式器
            IFormatter formatter = new BinaryFormatter();

            
//序列化
            formatter.Serialize(stream, obj);

            
//刷新流
            stream.Flush();

            
//取得字节数组
            byte[] theBytes = stream.ToArray();

            
//关闭流
            stream.Close();

            
//返回
            return theBytes;
        }


        
/// <summary>
        
/// 将序列化的byte[]还原为object对象,强制转换下类型即可恢复原对象
        
/// </summary>
        
/// <param name="theBytes">字节流</param>
        
/// <returns>对象</returns>

        public static object SerialByteToObj(byte[] theBytes)
        
{
            
//格式化器
            IFormatter formatter = new BinaryFormatter();

            
//内存流
            MemoryStream stream = new MemoryStream(theBytes);   //theBytes是序列化后的结果   

            
//反序列化取得对象
            object t = formatter.Deserialize(stream);

            
//关闭流
            stream.Close();

            
//返回对象
            return t;
        }

    }

}

你可能感兴趣的:(多线程,socket,Stream,服务器,byte,通讯)