[C#] C# socket 服务端与客户端通信演示代码 →→→→→进入此内容的聊天室

来自 , 2019-02-18, 写在 C#, 查看 102 次.
URL http://www.code666.cn/view/db079083
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. using System.Text;
  9. using System.Windows.Forms;
  10. using System.IO;
  11. using System.Threading;
  12. using System.Runtime.InteropServices;
  13.  
  14. public delegate void DGShowMsg(string strMsg);
  15. namespace Server
  16. {
  17.     public partial class Form1 : Form
  18.     {
  19.         public Form1()
  20.         {
  21.             InitializeComponent();
  22.             TextBox.CheckForIllegalCrossThreadCalls = false;//关闭跨线程修改控件检查
  23.             // txtIP.Text = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0].ToString();
  24.             txtIP.Text = Dns.GetHostByName(Dns.GetHostName()).AddressList[0].ToString();
  25.         }
  26.    
  27.         [DllImport("kernel32")] ///获取系统时间
  28.         public static extern void GetSystemTime(ref SYSTEMTIME_INFO stinfo);
  29.          
  30.  
  31.         ///定义系统时间结构信息
  32.         [StructLayout(LayoutKind.Sequential)]
  33.         public struct SYSTEMTIME_INFO
  34.         {
  35.             public ushort wYear;
  36.             public ushort wMonth;
  37.             public ushort wDayOfWeek;
  38.             public ushort wDay;
  39.             public ushort wHour;
  40.             public ushort wMinute;
  41.             public ushort wSecond;
  42.             public ushort wMilliseconds;
  43.         }
  44.  
  45.         Socket sokWatch = null;//负责监听 客户端段 连接请求的  套接字(女生宿舍的大妈)
  46.         Thread threadWatch = null;//负责 调用套接字, 执行 监听请求的线程
  47.          
  48.         //开启监听 按钮
  49.         private void btnStartListen_Click(object sender, EventArgs e)
  50.         {
  51.             //实例化 套接字 (ip4寻址协议,流式传输,TCP协议)
  52.             sokWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  53.                  
  54.             //创建 ip对象
  55.             IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
  56.            // IPAddress[] addressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
  57.             //string ip= this.geta
  58.             //创建网络节点对象 包含 ip和port
  59.            // IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim())); comboBox1.Text.Trim();
  60.             IPEndPoint endpoint = new IPEndPoint(address, int.Parse(comboBox1.Text.Trim()));
  61.             //将 监听套接字  绑定到 对应的IP和端口
  62.             sokWatch.Bind(endpoint);
  63.             //设置 监听队列 长度为10(同时能够处理 10个连接请求)
  64.             sokWatch.Listen(20);
  65.             threadWatch = new Thread(StartWatch);
  66.             threadWatch.IsBackground = true;
  67.             threadWatch.Start();
  68.             //txtShow.AppendText("启动服务器成功......rn");
  69.             label4.Text = "启动服务器成功......";
  70.              
  71.         }
  72.         //Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();
  73.         Dictionary<string, ConnectionClient> dictConn = new Dictionary<string, ConnectionClient>();
  74.  
  75.         bool isWatch = true;
  76.  
  77.         #region 1.被线程调用 监听连接端口
  78.         /// <summary>
  79.         /// 被线程调用 监听连接端口
  80.         /// </summary>
  81.         void StartWatch()
  82.         {
  83.             string recode;
  84.             while (isWatch)
  85.             {
  86.                 //threadWatch.SetApartmentState(ApartmentState.STA);
  87.                 //监听 客户端 连接请求,但是,Accept会阻断当前线程
  88.                 Socket sokMsg = sokWatch.Accept();//监听到请求,立即创建负责与该客户端套接字通信的套接字
  89.                 ConnectionClient connection = new ConnectionClient(sokMsg, ShowMsg, RemoveClientConnection);
  90.                 //将负责与当前连接请求客户端 通信的套接字所在的连接通信类 对象 装入集合
  91.                 dictConn.Add(sokMsg.RemoteEndPoint.ToString(), connection);
  92.                 //将 通信套接字 加入 集合,并以通信套接字的远程IpPort作为键
  93.                 //dictSocket.Add(sokMsg.RemoteEndPoint.ToString(), sokMsg);
  94.                 //将 通信套接字的 客户端IP端口保存在下拉框里
  95.                 cboClient.Items.Add(sokMsg.RemoteEndPoint.ToString());
  96.                 MessageBox.Show("有一个客户端新添加!");
  97.                 recode = sokMsg.RemoteEndPoint.ToString();
  98.                 //调用GetSystemTime函数获取系统时间信息
  99.                 SYSTEMTIME_INFO StInfo; StInfo = new SYSTEMTIME_INFO();
  100.                 GetSystemTime(ref StInfo);
  101.                 recode +="子计算机在"+StInfo.wYear.ToString() + "年" + StInfo.wMonth.ToString() + "月" + StInfo.wDay.ToString() + "日";
  102.                 recode += (StInfo.wHour + 8).ToString() + "点" + StInfo.wMinute.ToString() + "分" + StInfo.wSecond.ToString() + "秒"+"连接服务";
  103.                  
  104.                 //记录每台子计算机连接服务主机的日志
  105.                 StreamWriter m_sw = new StreamWriter(System.Windows.Forms.Application.StartupPath + @"\file.DAT", true);
  106.                 m_sw.WriteLine(recode);
  107.                 m_sw.WriteLine("------------------------------------------------------------------");
  108.                 m_sw.Close();
  109.                 //MessageBox.Show(recode);
  110.                 dictConn[sokMsg.RemoteEndPoint.ToString()].SendTrue();
  111.                 //启动一个新线程,负责监听该客户端发来的数据
  112.                 //Thread threadConnection = new Thread(ReciveMsg);
  113.                 //threadConnection.IsBackground = true;
  114.                 //threadConnection.Start(sokMsg);
  115.                  
  116.             }
  117.         }
  118.         #endregion
  119.  
  120.         //bool isRec = true;
  121.         //与客户端通信的套接字 是否 监听消息
  122.  
  123.         #region 发送消息 到指定的客户端 -btnSend_Click
  124.         //发送消息 到指定的客户端
  125.  
  126.         private void btnSend_Click(object sender, EventArgs e)
  127.         {
  128.             //byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(txtInput.Text.Trim());
  129.             //从下拉框中 获得 要哪个客户端发送数据
  130.             string time;
  131.             string connectionSokKey = cboClient.Text;
  132.             if (!string.IsNullOrEmpty(connectionSokKey))
  133.             {
  134.                 //从字典集合中根据键获得 负责与该客户端通信的套接字,并调用send方法发送数据过去
  135.                 dictConn[connectionSokKey].Send(txtInput.Text.Trim());
  136.                 SYSTEMTIME_INFO StInfo; StInfo = new SYSTEMTIME_INFO();
  137.                 GetSystemTime(ref StInfo);
  138.                 time = StInfo.wYear.ToString() + "/" + StInfo.wMonth.ToString() + "/" + StInfo.wDay.ToString() +"  ";
  139.                 time += (StInfo.wHour + 8).ToString() + ":" + StInfo.wMinute.ToString();
  140.                 richTextBox1.AppendText(time + "rn");
  141.                 richTextBox1.AppendText("对" + cboClient.Text +"说:"+ txtInput.Text.Trim() + "rn");
  142.                 txtInput.Text = "";
  143.                 //sokMsg.Send(arrMsg);
  144.             }
  145.             else
  146.             {
  147.                 MessageBox.Show("请选择要发送的子计算机~~");
  148.             }
  149.         }
  150.         #endregion
  151.  
  152.         //发送闪屏
  153.         private void btnShack_Click(object sender, EventArgs e)
  154.         {
  155.             string connectionSokKey = cboClient.Text;
  156.             if (!string.IsNullOrEmpty(connectionSokKey))
  157.             {
  158.                 dictConn[connectionSokKey].SendShake();
  159.             }
  160.             else
  161.             {
  162.                 MessageBox.Show("请选择要发送的子计算机~~");
  163.             }
  164.         }
  165.         //群闪
  166.         private void btnShackAll_Click(object sender, EventArgs e)
  167.         {
  168.             foreach (ConnectionClient conn in dictConn.Values)
  169.             {
  170.                 conn.SendShake();
  171.             }
  172.         }
  173.        
  174.         #region 2 移除与指定客户端的连接 +void RemoveClientConnection(string key)
  175.         /// <summary>
  176.         /// 移除与指定客户端的连接
  177.         /// </summary>
  178.         /// <param name="key">指定客户端的IP和端口</param>
  179.         public void RemoveClientConnection(string key)
  180.         {
  181.             if (dictConn.ContainsKey(key))
  182.             {
  183.                 dictConn.Remove(key);
  184.                 MessageBox.Show(key +"断开连接");
  185.                 cboClient.Items.Remove(key);
  186.             }
  187.         }
  188.         #endregion
  189.  
  190.         //选择要发送的文件
  191.         private void btnChooseFile_Click(object sender, EventArgs e)
  192.         {
  193.             OpenFileDialog ofd = new OpenFileDialog();
  194.             if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  195.             {
  196.                 txtFilePath.Text = ofd.FileName;
  197.             }
  198.         }
  199.  
  200.         //发送文件
  201.         private void btnSendFile_Click(object sender, EventArgs e)
  202.         {
  203.             //拿到下拉框中选中的客户端IPPORT
  204.             string key = cboClient.Text;
  205.             if (!string.IsNullOrEmpty(key))
  206.             {
  207.                 dictConn[key].SendFile(txtFilePath.Text.Trim());
  208.                // txtFilePath.Text = "";
  209.             }
  210.             else
  211.             {
  212.                 MessageBox.Show("请选择要发送的子计算机~");
  213.             }
  214.         }
  215.  
  216.         #region 向文本框显示消息 -void ShowMsg(string msgStr)
  217.         /// <summary>
  218.         /// 向文本框显示消息
  219.         /// </summary>
  220.         /// <param name="msgStr">消息</param>
  221.         public void ShowMsg(string msgStr)
  222.         {
  223.             //MessageBox.Show("1040414");
  224.             txtShow1.AppendText(msgStr + "rn");
  225.         }
  226.         #endregion
  227. //群消息
  228.         private void btnSendMsgAll_Click(object sender, EventArgs e)
  229.         {
  230.             string time;
  231.             foreach (ConnectionClient conn in dictConn.Values)
  232.             {
  233.                 conn.Send(txtInput.Text.Trim());
  234.                  
  235.             }
  236.             SYSTEMTIME_INFO StInfo; StInfo = new SYSTEMTIME_INFO();
  237.             GetSystemTime(ref StInfo);
  238.             time = StInfo.wYear.ToString() + "/" + StInfo.wMonth.ToString() + "/" + StInfo.wDay.ToString()  + "  ";
  239.             time += (StInfo.wHour + 8).ToString() + ":" + StInfo.wMinute.ToString();
  240.             richTextBox1.AppendText(time + "rn");
  241.             richTextBox1.AppendText("群发消息:"+ txtInput.Text.Trim() + "rn");
  242.             txtInput.Text = "";
  243.         }
  244. //群发文件
  245.         private void button1_Click(object sender, EventArgs e)
  246.         {
  247.  
  248.             foreach (ConnectionClient conn in dictConn.Values)
  249.             {
  250.                // dictConn.SendFile(txtFilePath.Text.Trim());
  251.                 conn.SendFile(txtFilePath.Text.Trim());
  252.                  
  253.  
  254.             }
  255.         }
  256.  
  257.         private void button2_Click(object sender, EventArgs e)
  258.         {
  259.             string connectionSokKey = cboClient.Text;
  260.             if (!string.IsNullOrEmpty(connectionSokKey))
  261.             {
  262.                 dictConn[connectionSokKey].guanji();
  263.             }
  264.             else
  265.             {
  266.                 MessageBox.Show("请选择要发送的子计算机~~");
  267.             }
  268.         }
  269.  
  270.         private void button3_Click(object sender, EventArgs e)
  271.         {
  272.             string connectionSokKey = cboClient.Text;
  273.             if (!string.IsNullOrEmpty(connectionSokKey))
  274.             {
  275.                 dictConn[connectionSokKey].chongqi();
  276.             }
  277.             else
  278.             {
  279.                 MessageBox.Show("请选择要发送的子计算机~~");
  280.             }
  281.         }
  282.  
  283.         private void button4_Click(object sender, EventArgs e)
  284.         {
  285.             string connectionSokKey = cboClient.Text;
  286.             if (!string.IsNullOrEmpty(connectionSokKey))
  287.             {
  288.                 dictConn[connectionSokKey].zhuxiao();
  289.             }
  290.             else
  291.             {
  292.                 MessageBox.Show("请选择要发送的子计算机~~");
  293.             }
  294.         }
  295.  
  296.         private void button5_Click(object sender, EventArgs e)
  297.         {
  298.             string connectionSokKey = cboClient.Text;
  299.             if (!string.IsNullOrEmpty(connectionSokKey))
  300.             {
  301.                 dictConn[connectionSokKey].jieping();
  302.             }
  303.             else
  304.             {
  305.                 MessageBox.Show("请选择要发送的子计算机~~");
  306.             }
  307.         }
  308.  
  309.        
  310.  
  311.     }
  312.     ///////////////////////////////////////////////////////////////////////////////////////
  313.    ////////////////////////////////////////////////////////////////////////////////////////
  314.    ////在这里,我新建了一个与客户端的通信和线程的类(ConnectionClient)//////////////////////
  315.     /// <summary>
  316.     /// 与客户端的 连接通信类(包含了一个 与客户端 通信的 套接字,和线程)
  317.     /// </summary>
  318.    public class ConnectionClient
  319.     {
  320.         Socket sokMsg;
  321.         DGShowMsg dgShowMsg;//负责 向主窗体文本框显示消息的方法委托
  322.         DGShowMsg dgRemoveConnection;// 负责 从主窗体 中移除 当前连接
  323.         Thread threadMsg;
  324.  
  325.         #region 构造函数
  326.         /// <summary>
  327.         ///
  328.         /// </summary>
  329.         /// <param name="sokMsg">通信套接字</param>
  330.         /// <param name="dgShowMsg">向主窗体文本框显示消息的方法委托</param>
  331.         public ConnectionClient(Socket sokMsg, DGShowMsg dgShowMsg, DGShowMsg dgRemoveConnection)
  332.         {
  333.             this.sokMsg = sokMsg;
  334.             this.dgShowMsg = dgShowMsg;
  335.             this.dgRemoveConnection = dgRemoveConnection;
  336.  
  337.             this.threadMsg = new Thread(RecMsg);
  338.             this.threadMsg.IsBackground = true;
  339.             this.threadMsg.Start();
  340.         }
  341.         #endregion
  342.  
  343.         bool isRec = true;
  344.         #region 02负责监听客户端发送来的消息
  345.         void RecMsg()
  346.         {
  347.             while (isRec)
  348.             {
  349.                 try
  350.                 {
  351.                     byte[] arrMsg = new byte[1024 * 1024 * 1];
  352.                     //接收 对应 客户端发来的消息
  353.                     int length = sokMsg.Receive(arrMsg);
  354.                     // string abc = Encoding.Default.GetString(arrMsg);
  355.                     // MessageBox.Show(abc);
  356.                     //将接收到的消息数组里真实消息转成字符串                                        
  357.                     if (arrMsg[0] == 1)
  358.                     {
  359.                          //string abc = Encoding.Default.GetString(arrMsg);
  360.                          //MessageBox.Show(abc);
  361.                          //发送来的是文件
  362.                          //MessageBox.Show("00000s");
  363.                          //SaveFileDialog sfd = new SaveFileDialog();
  364.                          SaveFileDialog sfd = new SaveFileDialog();
  365.                          sfd.Filter = "文本文件(.txt)|*.txt|所有文件(*.*)|*.*";
  366.                          // MessageBox.Show(sfd.Filter);
  367.                          
  368.                          //sfd.ShowDialog();
  369.                          //弹出文件保存选择框
  370.                          if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  371.                          {
  372.                              //MessageBox.Show("111110");
  373.                              //创建文件流
  374.                              using (FileStream fs = new FileStream(sfd.FileName, FileMode.OpenOrCreate))
  375.                              {
  376.                                  fs.Write(arrMsg, 1, length - 1);
  377.                                  MessageBox.Show("文件保存成功!");
  378.                              }
  379.                          }
  380.                      }
  381.                     /*else if(arrMsg[0] == 2)
  382.                     {
  383.                          
  384.                         //  MemoryStream ms = new MemoryStream(arrMsg, 0, length-1);
  385.                         MemoryStream ms = new MemoryStream(arrMsg);
  386.                         Image returnImage = Image.FromStream(ms);//??????????
  387.                         PictureBox district = (PictureBox)Application.OpenForms["Form1"].Controls["pictureBox1"].Controls["pictureBox1"];
  388.                         district.Image  =  returnImage;
  389.                        // this.saveFileDialog1.FileName = "";//清空名称栏
  390.                      
  391.                         /*  
  392.                          SaveFileDialog sfd = new SaveFileDialog();
  393.                         sfd.Filter = "图像文件(.jpg)|*.jpg|所有文件(*.*)|*.*";
  394.                         MessageBox.Show(sfd.Filter);
  395.                         if (DialogResult.OK == sfd.ShowDialog())
  396.                         {
  397.                             string strFileName = sfd.FileName;
  398.                             //Image img = (Image)this.pictureBox1.Image;
  399.                             returnImage.Save(strFileName);
  400.                         }
  401.                        
  402.                     }*/
  403.                      else//发送来的是消息
  404.                      {
  405.                         //MessageBox.Show("2222");
  406.                         string strMsg = sokMsg.RemoteEndPoint.ToString()+"说:"+"rn"+System.Text.Encoding.UTF8.GetString(arrMsg, 0, length); //// 我在这里  Request.ServerVariables.Get("Remote_Addr").ToString()+
  407.                         //通过委托 显示消息到 窗体的文本框
  408.                         dgShowMsg(strMsg);
  409.                       }
  410.                      
  411.                          
  412.                      
  413.                      //MessageBox.Show("11111");
  414.               }
  415.               catch (Exception ex)
  416.                {
  417.                   isRec = false;
  418.                  //从主窗体中 移除 下拉框中对应的客户端选择项,同时 移除 集合中对应的 ConnectionClient对象
  419.                     dgRemoveConnection(sokMsg.RemoteEndPoint.ToString());
  420.                 }
  421.             }
  422.         }
  423.         #endregion
  424.  
  425.         #region 03向客户端发送消息
  426.         /// <summary>
  427.         /// 向客户端发送消息
  428.         /// </summary>
  429.         /// <param name="strMsg"></param>
  430.         public void Send(string strMsg)
  431.         {
  432.             byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
  433.             byte[] arrMsgFinal = new byte[arrMsg.Length + 1];
  434.  
  435.             arrMsgFinal[0] = 0;//设置 数据标识位等于0,代表 发送的是 文字
  436.             arrMsg.CopyTo(arrMsgFinal, 1);
  437.  
  438.             sokMsg.Send(arrMsgFinal);
  439.         }
  440.         #endregion
  441.  
  442.         #region 04向客户端发送文件数据 +void SendFile(string strPath)
  443.         /// <summary>
  444.         /// 04向客户端发送文件数据
  445.         /// </summary>
  446.         /// <param name="strPath">文件路径</param>
  447.         public void SendFile(string strPath)
  448.         {
  449.             //通过文件流 读取文件内容
  450.             //MessageBox.Show("12540");
  451.             using (FileStream fs = new FileStream(strPath, FileMode.OpenOrCreate))
  452.             {
  453.                 byte[] arrFile = new byte[1024 * 1024 * 2];
  454.                 //读取文件内容到字节数组,并 获得 实际文件大小
  455.                 int length = fs.Read(arrFile, 0, arrFile.Length);
  456.                 //定义一个 新数组,长度为文件实际长度 +1
  457.                 byte[] arrFileFina = new byte[length + 1];
  458.                 arrFileFina[0] = 1;//设置 数据标识位等于1,代表 发送的是文件
  459.                 //将 文件数据数组 复制到 新数组中,下标从1开始
  460.                 //arrFile.CopyTo(arrFileFina, 1);
  461.                 Buffer.BlockCopy(arrFile, 0, arrFileFina, 1, length);
  462.                // MessageBox.Show("120");
  463.                 //发送文件数据
  464.                 sokMsg.Send(arrFileFina);//, 0, length + 1, SocketFlags.None);
  465.             }
  466.         }
  467.         #endregion
  468.  
  469.         #region 05向客户端发送闪屏
  470.         /// <summary>
  471.         /// 向客户端发送闪屏
  472.         /// </summary>
  473.         /// <param name="strMsg"></param>
  474.         public void SendShake()
  475.         {
  476.             byte[] arrMsgFinal = new byte[1];
  477.             arrMsgFinal[0] = 2;
  478.             sokMsg.Send(arrMsgFinal);
  479.         }
  480.         #endregion
  481.  
  482.         #region 06关闭与客户端连接
  483.         /// <summary>
  484.         /// 关闭与客户端连接
  485.         /// </summary>
  486.         public void CloseConnection()
  487.         {
  488.             isRec = false;
  489.         }
  490.         #endregion
  491.  
  492.         #region 07向客户端发送连接成功提示
  493.         /// <summary>
  494.         /// 向客户端发送连接成功提示
  495.         /// </summary>
  496.         /// <param name="strMsg"></param>
  497.         public void SendTrue()
  498.         {
  499.             byte[] arrMsgFinal = new byte[1];
  500.             arrMsgFinal[0] = 3;
  501.             sokMsg.Send(arrMsgFinal);
  502.         }
  503.         #endregion
  504.  
  505.         #region 08向客户端发送关机命令
  506.         /// <summary>
  507.         /// 向客户端发送关机命令
  508.         /// </summary>
  509.         /// <param name="strMsg"></param>
  510.         public void guanji()
  511.         {
  512.             byte[] arrMsgFinal = new byte[1];
  513.             arrMsgFinal[0] = 4;
  514.             sokMsg.Send(arrMsgFinal);
  515.         }
  516.         #endregion
  517.  
  518.         #region 09向客户端发送重启命令
  519.         /// <summary>
  520.         /// 向客户端发送关机命令
  521.         /// </summary>
  522.         /// <param name="strMsg"></param>
  523.         public void chongqi()
  524.         {
  525.             byte[] arrMsgFinal = new byte[1];
  526.             arrMsgFinal[0] = 5;
  527.             sokMsg.Send(arrMsgFinal);
  528.         }
  529.         #endregion
  530.  
  531.         #region 10向客户端发送待机命令
  532.         /// <summary>
  533.         /// 向客户端发送关机命令
  534.         /// </summary>
  535.         /// <param name="strMsg"></param>
  536.         public void zhuxiao()
  537.         {
  538.             byte[] arrMsgFinal = new byte[1];
  539.             arrMsgFinal[0] = 6;
  540.             sokMsg.Send(arrMsgFinal);
  541.         }
  542.        #endregion
  543.  
  544.         #region 11向客户端发送截屏命令
  545.         /// <summary>
  546.         /// 向客户端发送截屏命令
  547.         /// </summary>
  548.         /// <param name="strMsg"></param>
  549.         public void jieping()
  550.         {
  551.             byte[] arrMsgFinal = new byte[1];
  552.             arrMsgFinal[0] = 7;
  553.             sokMsg.Send(arrMsgFinal);
  554.         }
  555.         #endregion
  556.     }
  557.  
  558. }
  559.  
  560.  
  561. //csharp/6777

回复 "C# socket 服务端与客户端通信演示代码"

这儿你可以回复上面这条便签

captcha