using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace _06ServerB { public partial class Form1 : Form { public Form1() { InitializeComponent(); } void ShowMsg(string str)//給消息文本框加文本的方法 { txtLog.AppendText(str + "\r\n"); } private void btnStart_Click(object sender, EventArgs e) { try { IPAddress ip = IPAddress.Any;//創建IP//Any 字段等效於以點分隔的四部分表示法格式的 0.0.0.0 這個IP地址,實際是一個廣播地址。//對於SOCKET而言,使用 any ,表示,偵聽本機的所有IP地址的對應的端口(本機可能有多個IP或只有一個IP) IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));//創建終結點(EndPoint) Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//建立監視的Socket socketWatch.Bind(point);//使得Socket綁定Bind()端口,參數為EndPoint//監聽 Console.WriteLine("監聽成功"); ShowMsg("監聽成功"); socketWatch.Listen(0);//參數是監聽的最大長度,0是無限 Thread th = new Thread(Listen);//新建線程,運行soketWatch(),這里的Listen是自定義的方法 th.IsBackground = true;//線程為后台屬性 th.Start(socketWatch);//提供線程要執行的方法的要使用的數據(參數)的對象 } catch { } } Socket socketSend;//聲明 socketSend 用於等待客戶端的連接 並且創建與之通信用的SocketSend,//等客戶端連接//接受到client連接,為此連接建立新的socket,並接受信息 Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();//將遠程連接的客戶端的IP地址和Socket存入集合中 void Listen(object o)//被線程執行的函數,用於Accept()新建Socket,把每次的新建Socket,添加RemoteEndPoint到Dic集合,添加到cbo下拉列表框,有參數的話,必須是object類型 { Socket socketWatch = o as Socket;//as 強轉語句,object o參數強轉為Socket類型 while (true) { try { socketSend = socketWatch.Accept();//等待客戶端的連接 並且創建一個負責通信的Socket dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);//將遠程連接的客戶端的IP地址和Socket存入集合中 cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());//將遠程連接的客戶端的IP地址和端口號存儲下拉框中 ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + "連接成功");//192.168.11.78:連接成功 Thread th = new Thread(Recive);//開啟 一個新線程不停的接受客戶端發送過來的消息 th.IsBackground = true; th.Start(socketSend); } catch { } } } void Recive(object o)//被線程執行的函數,用於服務器端不停的接受客戶端發送過來的消息,並打印出來 { Socket socketSend = o as Socket; while (true) { try { //客戶端連接成功后,服務器應該接受客戶端發來的消息 byte[] buffer = new byte[1024 * 1024 * 2]; //實際接受到的有效字節數 int r = socketSend.Receive(buffer); if (r == 0) { break; } string str = Encoding.UTF8.GetString(buffer, 0, r); ShowMsg(socketSend.RemoteEndPoint + ":" + str); } catch { } } } private void btnSelect_Click(object sender, EventArgs e)// 選擇要發送的文件 { OpenFileDialog ofd = new OpenFileDialog(); ofd.InitialDirectory = @"C:\Users\SpringRain\Desktop"; ofd.Title = "請選擇要發送的文件"; ofd.Filter = "所有文件|*.*"; ofd.ShowDialog(); txtPath.Text = ofd.FileName; } //自定義協議,在傳遞的字節數組前面加上一個字節作為標識,0表示文字,1表示文件,2表示震動 private void btnSend_Click(object sender, EventArgs e)//服務器給客戶端發送消息 { string str = txtMsg.Text;//消息框文本 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str); List<byte> list = new List<byte>();//存入list list.Add(0);//是自定義協議,在傳遞的字節數組前面加上一個字節作為標識,0表示文字,1表示文件 list.AddRange(buffer);//添加buffer數組進集合list byte[] newBuffer = list.ToArray();//將泛型集合轉換為數組 string ip = cboUsers.SelectedItem.ToString(); //獲得用戶在下拉框中選中的IP地址 dicSocket[ip].Send(newBuffer);//Socket.Send()將數據發送到連接的Socket//socketSend.Send(buffer); } private void btnSendFile_Click(object sender, EventArgs e) { //獲得要發送文件的路徑 string path = txtPath.Text; using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read)) { byte[] buffer = new byte[1024 * 1024 * 5]; int r = fsRead.Read(buffer, 0, buffer.Length); List<byte> list = new List<byte>(); list.Add(1); list.AddRange(buffer); byte[] newBuffer = list.ToArray(); dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer, 0, r+1, SocketFlags.None); } } /// <summary> /// 發送震動 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnZD_Click(object sender, EventArgs e) { byte[] buffer = new byte[1]; buffer[0] = 2; dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer); } } }