C# Socket多线程编程(一)

//实现服务器端//创建Client类using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ChartServer{/// <summary>/// 客户端连接/// </summary>class Client{#region 字段//客户端连接线程private System.Threading.Thread clthread;//客户端连接网络地址private System.Net.EndPoint endpoint;//客户端名称private string name;//客户端对象private System.Net.Sockets.Socket sock;#endregion#region 构造//构造一个客户端连接public Client(string _name, System.Net.EndPoint _endpoint, System.Threading.Thread _thread, System.Net.Sockets.Socket _sock){clthread = _thread;endpoint = _endpoint;name = _name;sock = _sock;}#endregion#region 方法//重写ToString方法public override string ToString(){//返回客户端连接网络地址和客户端连接名称return endpoint.ToString() + ":" + name;}#endregion#region 属性public System.Threading.Thread CLThread{get { return clthread; }set { clthread = value; }}public System.Net.EndPoint Host{get { return endpoint; }set { endpoint = value; }}public string Name{get { return name; }set { name = value; }}public System.Net.Sockets.Socket Sock{get { return sock; }set { sock = value; }}#endregion}}//服务器端代码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;namespace ChartServer{public partial class ServerMain : Form{public ServerMain(){InitializeComponent();}//客户端连接System.Net.Sockets.Socket clientsocket;//连接集合System.Collections.ArrayList clients;//客户端线程System.Threading.Thread clientservice;System.Threading.Thread threadListen;System.Net.Sockets.TcpListener listener;System.Net.IPAddress ipAddress;Int32 listenport;public delegate void MyInvoke(string str);/// <summary>/// 开始侦听,允许客户端连接/// </summary>private void StartListening(){//定义网络连接侦听listener = new System.Net.Sockets.TcpListener(ipAddress,listenport);listener.Start();while (true){try{//开始侦听网络连接clientsocket = listener.AcceptSocket();//客户端连接线程clientservice = new System.Threading.Thread(new System.Threading.ThreadStart(ServiceClient));//启动线程clientservice.Start();}catch (Exception e){MessageBox.Show("listening Error:" + e.Message);}}}private void ServiceClient(){//获取一个客户端连接System.Net.Sockets.Socket client = clientsocket;//定义一个是否存活的变量bool keepalive = true;//判断新连接是否存在if (client == null) keepalive = false;else keepalive = true;//判断客户端是否还存在while (keepalive){//定义字节Byte[] buffer = new Byte[1024];//定义数据量int bufLen = 0;try{//从客户端接收到的数据量bufLen = client.Available;//接收客户端发过来的数据client.Receive(buffer, 0, bufLen, System.Net.Sockets.SocketFlags.None);//假如客户端没有传入数据,则返回if (bufLen == 0) continue;//将字节转换为字符串string clientcommand = System.Text.Encoding.ASCII.GetString(buffer).Substring(0, bufLen);//分割从客户端传入的字符串string[] tokens = clientcommand.Split(new Char[] { ‘|’ });//输出到控制台Console.WriteLine(clientcommand);//CONN:表示新建连接。发送格式:CONN|发送者名称if (tokens[0] == "CONN"){//循环所有的客户端for (int n = 0; n < clients.Count; n++){//循环获取连接对象Client cl = (Client)clients[n];//向所有客户端发送新添加连接消息SendToClient(cl, "JOIN|" + tokens[1]);}//获取新添加连接的网络地址System.Net.EndPoint ep = client.RemoteEndPoint;//新建一个客户端连接,保存连接信息Client c = new Client(tokens[1], ep, clientservice, client);//将新连接添加到集合中clients.Add(c);//创建信息string message = "LIST|" + GetChatterList() + "/r/n";//将连接集合发送给新连接。SendToClient(c, message);//创建线程 将新连接添加到当前连接集合中,使用匿名委托调用添加方法System.Threading.Thread handlerControl = new System.Threading.Thread(delegate() { handlerListBox(c.Name + "|" + c.Host.ToString(), "add"); });//启动线程handlerControl.Start();}//CHAT:发送全局消息,所有其他连接都可以接收到。发送格式:CHAT|发送者名称|信息内容if (tokens[0] == "CHAT"){//循环连接集合for (int n = 0; n < clients.Count; n++){//获取当前连接Client cl = (Client)clients[n];//发送消息SendToClient(cl, clientcommand);}}//PRIV:发送私聊信息。发送格式:PRIV|发送者名称|信息内容|接受者名称if (tokens[0] == "PRIV"){//获取接受者连接名称string destclient = tokens[3];//循环集合列表for (int n = 0; n < clients.Count; n++){//获取连接Client cl = (Client)clients[n];//如果是接受者if (cl.Name.CompareTo(tokens[3]) == 0)//发送消息SendToClient(cl, clientcommand);//如果是发送者if (cl.Name.CompareTo(tokens[1]) == 0)//发送消息SendToClient(cl, clientcommand);}}//GONE 退出。发送格式:GONE|发送者名称if (tokens[0] == "GONE"){//连接索引int remove = 0;//是否存在bool found = false;//当前连接数int c = clients.Count;//连接名称string clientname = "";//遍历集合for (int n = 0; n < clients.Count; n++){//获取连接Client cl = (Client)clients[n];//如果不是要退出的连接if (cl.Name.CompareTo(tokens[1]) != 0)//发送消息SendToClient(cl, clientcommand);else{//发送确认退出信息SendToClient(cl, "QUIT|");//获取连接名称clientname = cl.Name + "|" + cl.Host.ToString();//获取连接索引remove = n;//连接存在found = true;}}//连接存在if (found){//创建删除连接线程,,从列表中删除连接System.Threading.Thread t = new System.Threading.Thread(delegate() { handlerListBox( clientname, "del"); });//启动线程t.Start();//从集合中删除连接clients.RemoveAt(remove);//改变存活状态keepalive = false;}}}catch (Exception e){MessageBox.Show("Receive Error:" + e.Message);keepalive = false;}}}/// <summary>/// 获取当前连接集合/// </summary>/// <returns></returns>private string GetChatterList(){string result = "";//循环集合,获取连接名称。for (int i = 0; i < clients.Count; i++){//使用“|”分隔result += ((Client)clients[i]).Name + "|";}return result;}/// <summary>/// 发送信息到客户端/// </summary>/// <param name="cl">客户端连接</param>/// <param name="clientCommand">要发送的信息</param>private void SendToClient(Client cl, string clientCommand){//将字符串转换成字节Byte[] message = System.Text.Encoding.ASCII.GetBytes(clientCommand);//获取连接对象System.Net.Sockets.Socket s = cl.Sock;//判断是否还在连接状态if (s.Connected){//发送消息s.Send(message, message.Length, 0);}}/// <summary>/// 加载窗体类/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void ServerMain_Load(object sender, EventArgs e){//创建连接集合clients = new System.Collections.ArrayList();}/// <summary>/// 监听按钮/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnStartListening_Click(object sender, EventArgs e){this.btnStartListening.Enabled = false;//获取服务器端IP地址ipAddress = System.Net.IPAddress.Parse("192.168.104.110");//获取服务器端口号listenport = 6666;//创建监听线程threadListen = new System.Threading.Thread(StartListening);//启动线程threadListen.Start();//创建设置状态文本线程System.Threading.Thread handlerControl = new System.Threading.Thread( delegate() { SetText("Listening…"); });//启动线程handlerControl.Start();}/// <summary>/// 设置连接文本/// </summary>/// <param name="s"></param>private void SetText(string s){//判断是否是本线程调用if (lblMessage.InvokeRequired){//如果不是,则使用委托,改变为本线程调用MyInvoke _myInvoke = new MyInvoke(SetText);//执行委托,传入参数this.Invoke(_myInvoke, new object[] { s });}else{//改变文本值this.lblMessage.Text = s;}}private void handlerListBox(string c, string o){//判断是否是本线程调用if (lbClients.InvokeRequired){//创建委托MyInvoke _myInvoke;//要执行的操作if (o == "add")_myInvoke = new MyInvoke(addItem);else_myInvoke = new MyInvoke(delItem);//执行委托,将参数传入this.Invoke(_myInvoke, new object[] { c });}}/// <summary>/// 在当前连接列表中删除一个连接/// </summary>/// <param name="c"></param>private void delItem(string c){this.lbClients.Items.Remove(c);}/// <summary>/// 在当前连接列表中新建一个连接/// </summary>/// <param name="c"></param>private void addItem(string c){this.lbClients.Items.Add(c);}}}

不甚酒力,体会不了酒的美味,但却能感受知已的妙处。

C# Socket多线程编程(一)

相关文章:

你感兴趣的文章:

标签云: