C# Socket多线程编程(一)

转自:http://blog.csdn.net/liguo9860/article/details/6148614



[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //实现服务器端  
  2.   
  3. //创建Client类  
  4.   
  5. using System;  
  6. using System.Collections.Generic;  
  7. using System.Linq;  
  8. using System.Text;  
  9.   
  10. namespace ChartServer  
  11. {  
  12.     /// <summary>  
  13.     /// 客户端连接  
  14.     /// </summary>  
  15.     class Client  
  16.     {  
  17.         #region 字段  
  18.         //客户端连接线程  
  19.         private System.Threading.Thread clthread;  
  20.         //客户端连接网络地址  
  21.         private System.Net.EndPoint endpoint;  
  22.         //客户端名称  
  23.         private string name;  
  24.         //客户端对象  
  25.         private System.Net.Sockets.Socket sock;  
  26.         #endregion  
  27.         #region 构造  
  28.         //构造一个客户端连接  
  29.         public Client(string _name, System.Net.EndPoint _endpoint, System.Threading.Thread _thread, System.Net.Sockets.Socket _sock)  
  30.         {  
  31.             clthread = _thread;  
  32.             endpoint = _endpoint;  
  33.             name = _name;  
  34.             sock = _sock;  
  35.         }  
  36.         #endregion  
  37.         #region 方法  
  38.         //重写ToString方法  
  39.         public override string ToString()  
  40.         {  
  41.             //返回客户端连接网络地址和客户端连接名称  
  42.             return endpoint.ToString() + ":" + name;  
  43.         }  
  44.         #endregion  
  45.         #region 属性  
  46.         public System.Threading.Thread CLThread  
  47.         {  
  48.             get { return clthread; }  
  49.             set { clthread = value; }  
  50.         }  
  51.         public System.Net.EndPoint Host  
  52.         {  
  53.             get { return endpoint; }  
  54.             set { endpoint = value; }  
  55.         }  
  56.         public string Name  
  57.         {  
  58.             get { return name; }  
  59.             set { name = value; }  
  60.         }  
  61.         public System.Net.Sockets.Socket Sock  
  62.         {  
  63.             get { return sock; }  
  64.             set { sock = value; }  
  65.         }  
  66.         #endregion  
  67.     }  
  68. }  
  69.   
  70. //服务器端代码  
  71.   
  72. using System;  
  73. using System.Collections.Generic;  
  74. using System.ComponentModel;  
  75. using System.Data;  
  76. using System.Drawing;  
  77. using System.Linq;  
  78. using System.Text;  
  79. using System.Windows.Forms;  
  80.   
  81. namespace ChartServer  
  82. {  
  83.     public partial class ServerMain : Form  
  84.     {  
  85.         public ServerMain()  
  86.         {  
  87.             InitializeComponent();  
  88.         }  
  89.   
  90.         //客户端连接  
  91.         System.Net.Sockets.Socket clientsocket;  
  92.         //连接集合  
  93.         System.Collections.ArrayList clients;  
  94.         //客户端线程  
  95.         System.Threading.Thread clientservice;  
  96.         System.Threading.Thread threadListen;  
  97.         System.Net.Sockets.TcpListener listener;  
  98.         System.Net.IPAddress ipAddress;  
  99.         Int32 listenport;  
  100.         public delegate void MyInvoke(string str);  
  101.         /// <summary>  
  102.         /// 开始侦听,允许客户端连接  
  103.         /// </summary>  
  104.         private void StartListening()  
  105.         {  
  106.             //定义网络连接侦听  
  107.             listener = new System.Net.Sockets.TcpListener(ipAddress,listenport);  
  108.   
  109.             listener.Start();  
  110.             while (true)  
  111.             {  
  112.                 try  
  113.                 {  
  114.                     //开始侦听网络连接                      
  115.                     clientsocket = listener.AcceptSocket();  
  116.                     //客户端连接线程  
  117.                     clientservice = new System.Threading.Thread(new System.Threading.ThreadStart(ServiceClient));  
  118.                     //启动线程  
  119.                     clientservice.Start();  
  120.                 }  
  121.                 catch (Exception e)  
  122.                 {  
  123.                     MessageBox.Show("listening Error:" + e.Message);  
  124.                 }  
  125.             }  
  126.         }  
  127.         private void ServiceClient()  
  128.         {  
  129.             //获取一个客户端连接  
  130.             System.Net.Sockets.Socket client = clientsocket;  
  131.             //定义一个是否存活的变量  
  132.             bool keepalive = true;  
  133.             //判断新连接是否存在  
  134.             if (client == null) keepalive = false;  
  135.             else keepalive = true;  
  136.             //判断客户端是否还存在  
  137.             while (keepalive)  
  138.             {  
  139.                 //定义字节  
  140.                 Byte[] buffer = new Byte[1024];  
  141.                 //定义数据量  
  142.                 int bufLen = 0;  
  143.                 try  
  144.                 {  
  145.                     //从客户端接收到的数据量  
  146.                     bufLen = client.Available;  
  147.                     //接收客户端发过来的数据  
  148.                     client.Receive(buffer, 0, bufLen, System.Net.Sockets.SocketFlags.None);  
  149.                     //假如客户端没有传入数据,则返回  
  150.                     if (bufLen == 0) continue;  
  151.   
  152.                     //将字节转换为字符串  
  153.                     string clientcommand = System.Text.Encoding.ASCII.GetString(buffer).Substring(0, bufLen);  
  154.                     //分割从客户端传入的字符串  
  155.                     string[] tokens = clientcommand.Split(new Char[] { '|' });  
  156.                     //输出到控制台  
  157.                     Console.WriteLine(clientcommand);  
  158.                     //CONN:表示新建连接。发送格式:CONN|发送者名称  
  159.                     if (tokens[0] == "CONN")  
  160.                     {  
  161.                         //循环所有的客户端  
  162.                         for (int n = 0; n < clients.Count; n++)  
  163.                         {  
  164.                             //循环获取连接对象  
  165.                             Client cl = (Client)clients[n];  
  166.                             //向所有客户端发送新添加连接消息  
  167.                             SendToClient(cl, "JOIN|" + tokens[1]);  
  168.                         }  
  169.                         //获取新添加连接的网络地址  
  170.                         System.Net.EndPoint ep = client.RemoteEndPoint;  
  171.                         //新建一个客户端连接,保存连接信息  
  172.                         Client c = new Client(tokens[1], ep, clientservice, client);  
  173.                         //将新连接添加到集合中  
  174.                         clients.Add(c);  
  175.                         //创建信息  
  176.                         string message = "LIST|" + GetChatterList() + "/r/n";  
  177.                         //将连接集合发送给新连接。  
  178.                         SendToClient(c, message);  
  179.                         //创建线程 将新连接添加到当前连接集合中,使用匿名委托调用添加方法  
  180.                         System.Threading.Thread handlerControl = new System.Threading.Thread(delegate() { handlerListBox(c.Name + "|" + c.Host.ToString(), "add"); });  
  181.                         //启动线程  
  182.                         handlerControl.Start();  
  183.                     }  
  184.                     //CHAT:发送全局消息,所有其他连接都可以接收到。发送格式:CHAT|发送者名称|信息内容  
  185.                     if (tokens[0] == "CHAT")  
  186.                     {  
  187.                         //循环连接集合  
  188.                         for (int n = 0; n < clients.Count; n++)  
  189.                         {  
  190.                             //获取当前连接  
  191.                             Client cl = (Client)clients[n];  
  192.                             //发送消息  
  193.                             SendToClient(cl, clientcommand);  
  194.                         }  
  195.                     }  
  196.                     //PRIV:发送私聊信息。发送格式:PRIV|发送者名称|信息内容|接受者名称  
  197.                     if (tokens[0] == "PRIV")  
  198.                     {  
  199.                         //获取接受者连接名称  
  200.                         string destclient = tokens[3];  
  201.                         //循环集合列表  
  202.                         for (int n = 0; n < clients.Count; n++)  
  203.                         {  
  204.                             //获取连接  
  205.                             Client cl = (Client)clients[n];  
  206.                             //如果是接受者  
  207.                             if (cl.Name.CompareTo(tokens[3]) == 0)  
  208.                                 //发送消息  
  209.                                 SendToClient(cl, clientcommand);  
  210.                             //如果是发送者  
  211.                             if (cl.Name.CompareTo(tokens[1]) == 0)  
  212.                                 //发送消息  
  213.                                 SendToClient(cl, clientcommand);  
  214.                         }  
  215.                     }  
  216.                     //GONE 退出。发送格式:GONE|发送者名称  
  217.                     if (tokens[0] == "GONE")  
  218.                     {  
  219.                         //连接索引  
  220.                         int remove = 0;  
  221.                         //是否存在  
  222.                         bool found = false;  
  223.                         //当前连接数  
  224.                         int c = clients.Count;  
  225.                         //连接名称  
  226.                         string clientname = "";  
  227.                         //遍历集合  
  228.                         for (int n = 0; n < clients.Count; n++)  
  229.                         {  
  230.                             //获取连接  
  231.                             Client cl = (Client)clients[n];  
  232.                             //如果不是要退出的连接  
  233.                             if (cl.Name.CompareTo(tokens[1]) != 0)  
  234.                                 //发送消息  
  235.                                 SendToClient(cl, clientcommand);  
  236.                             else  
  237.                             {  
  238.                                 //发送确认退出信息  
  239.                                 SendToClient(cl, "QUIT|");  
  240.                                 //获取连接名称  
  241.                                 clientname = cl.Name + "|" + cl.Host.ToString();  
  242.                                 //获取连接索引  
  243.                                 remove = n;  
  244.                                 //连接存在  
  245.                                 found = true;  
  246.                             }  
  247.                         }  
  248.                         //连接存在  
  249.                         if (found)  
  250.                         {  
  251.                             //创建删除连接线程,从列表中删除连接  
  252.                             System.Threading.Thread t = new System.Threading.Thread(delegate() { handlerListBox( clientname, "del"); });  
  253.                             //启动线程  
  254.                             t.Start();  
  255.                             //从集合中删除连接  
  256.                             clients.RemoveAt(remove);  
  257.                             //改变存活状态  
  258.                             keepalive = false;  
  259.                         }  
  260.                     }  
  261.                 }  
  262.                 catch (Exception e)  
  263.                 {  
  264.                     MessageBox.Show("Receive Error:" + e.Message);  
  265.                     keepalive = false;  
  266.                 }  
  267.             }  
  268.         }  
  269.         /// <summary>  
  270.         /// 获取当前连接集合  
  271.         /// </summary>  
  272.         /// <returns></returns>  
  273.         private string GetChatterList()  
  274.         {  
  275.             string result = "";  
  276.             //循环集合,获取连接名称。  
  277.             for (int i = 0; i < clients.Count; i++)  
  278.             {  
  279.                 //使用“|”分隔  
  280.                 result += ((Client)clients[i]).Name + "|";  
  281.             }  
  282.             return result;  
  283.         }  
  284.         /// <summary>  
  285.         /// 发送信息到客户端  
  286.         /// </summary>  
  287.         /// <param name="cl">客户端连接</param>  
  288.         /// <param name="clientCommand">要发送的信息</param>  
  289.         private void SendToClient(Client cl, string clientCommand)  
  290.         {  
  291.             //将字符串转换成字节  
  292.             Byte[] message = System.Text.Encoding.ASCII.GetBytes(clientCommand);  
  293.             //获取连接对象  
  294.             System.Net.Sockets.Socket s = cl.Sock;  
  295.             //判断是否还在连接状态  
  296.             if (s.Connected)  
  297.             {  
  298.                 //发送消息  
  299.                 s.Send(message, message.Length, 0);  
  300.             }  
  301.         }  
  302.         /// <summary>  
  303.         /// 加载窗体类  
  304.         /// </summary>  
  305.         /// <param name="sender"></param>  
  306.         /// <param name="e"></param>  
  307.         private void ServerMain_Load(object sender, EventArgs e)  
  308.         {  
  309.             //创建连接集合  
  310.             clients = new System.Collections.ArrayList();  
  311.         }  
  312.         /// <summary>  
  313.         /// 监听按钮  
  314.         /// </summary>  
  315.         /// <param name="sender"></param>  
  316.         /// <param name="e"></param>  
  317.         private void btnStartListening_Click(object sender, EventArgs e)  
  318.         {  
  319.             this.btnStartListening.Enabled = false;  
  320.             //获取服务器端IP地址  
  321.             ipAddress = System.Net.IPAddress.Parse("192.168.104.110");  
  322.             //获取服务器端口号  
  323.             listenport = 6666;  
  324.             //创建监听线程  
  325.             threadListen = new System.Threading.Thread(StartListening);  
  326.             //启动线程  
  327.             threadListen.Start();  
  328.             //创建设置状态文本线程  
  329.             System.Threading.Thread handlerControl = new System.Threading.Thread( delegate() { SetText("Listening..."); });  
  330.             //启动线程  
  331.             handlerControl.Start();  
  332.         }  
  333.         /// <summary>  
  334.         /// 设置连接文本  
  335.         /// </summary>  
  336.         /// <param name="s"></param>  
  337.         private void SetText(string s)  
  338.         {  
  339.             //判断是否是本线程调用  
  340.             if (lblMessage.InvokeRequired)  
  341.             {  
  342.                 //如果不是,则使用委托,改变为本线程调用  
  343.                 MyInvoke _myInvoke = new MyInvoke(SetText);  
  344.                 //执行委托,传入参数  
  345.                 this.Invoke(_myInvoke, new object[] { s });  
  346.             }  
  347.             else  
  348.             {  
  349.                 //改变文本值  
  350.                 this.lblMessage.Text = s;  
  351.             }  
  352.         }  
  353.   
  354.         private void handlerListBox(string c, string o)  
  355.         {  
  356.             //判断是否是本线程调用  
  357.             if (lbClients.InvokeRequired)  
  358.             {  
  359.                 //创建委托  
  360.                 MyInvoke _myInvoke;  
  361.                 //要执行的操作  
  362.                 if (o == "add")  
  363.                     _myInvoke = new MyInvoke(addItem);  
  364.                 else  
  365.                     _myInvoke = new MyInvoke(delItem);  
  366.                 //执行委托,将参数传入  
  367.                 this.Invoke(_myInvoke, new object[] { c });  
  368.             }  
  369.         }  
  370.         /// <summary>  
  371.         /// 在当前连接列表中删除一个连接  
  372.         /// </summary>  
  373.         /// <param name="c"></param>  
  374.         private void delItem(string c)  
  375.         {  
  376.             this.lbClients.Items.Remove(c);  
  377.         }  
  378.         /// <summary>  
  379.         /// 在当前连接列表中新建一个连接  
  380.         /// </summary>  
  381.         /// <param name="c"></param>  
  382.         private void addItem(string c)  
  383.         {  
  384.             this.lbClients.Items.Add(c);  
  385.         }  
  386.     }  
  387. }  


    下载地址:示例代码下载



C#多线程Socket编程 在程序设计中,涉及数据存储和数据交换的时候,不管是B/S还是C/S模式 ,都有这样一个概念:数据库服务器。这要求一台性能和配置都比较好的主机作为服务器, 以满足数目众多的客户端进行频繁访问。但是对于一些数据交换的要求不主同,而且涉及到的通讯个体数目不多,如果还采用“一主机多客户机”的模式, 便要求一台硬件配置良好而且软件上安装了相关数据服务软件,这样会造成硬件和软件上的很多不必要的成本,这时Socket在点对点的平行对象之间的网络通讯的优势就就发挥出来了。 其实对于Socket通讯来说,服务器和客户端的界定不像数据库服务器与客户端那样明显,甚至可以说Socket通讯里面的服务器和客户端只是相对的, 因为网络通讯的对象基本上是处于平等层面的,只是为了方便对两台联网通讯的主机的描述才这样定义称谓的。 由于在.NET中Socket通讯的建立很容易,所以本文主要介绍一个Socket的比较典型的应用的流程:客户端向服务器发送图片请求,图片服务器接收到请求, 并将服务器硬盘上的图片编码,发送到客户端,客户端得到图片数据后,再将这些数据写成图片文件,保存在客户端上。 本文主要是对Socket的一个应用进行介绍,所以至于其原理在此没有深究,至于如何建立Socket还有如何实现网络的七层协议在此都没有进行相关研究和介绍, 本文主要介绍如何实现一个用户想要的功能,即在两台主机之间进行通讯,通过网络来收发用户想要收发的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值