利用socket以及多線程、文件流等方法實現(xiàn)通信,互發(fā)文本信息以及文件
服務器端:
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 通訊程序再寫一次 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Socket socketListen; private void btnListen_Click(object sender, EventArgs e) { try { //創(chuàng)建監(jiān)聽socket socketListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //獲取ip IPAddress ip = IPAddress.Parse(txtIP.Text); //獲取端口號 IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPoint.Text)); //將負責監(jiān)聽的socket綁定這個端口號 socketListen.Bind(point); ShowMsg("開始監(jiān)聽!"); //設置監(jiān)聽隊列,就是在同一時間允許連接的端口數(shù)量 socketListen.Listen(10); //創(chuàng)建一個新線程來執(zhí)行這個一直在監(jiān)聽中的方法 Thread th = new Thread(Listen); th.IsBackground = true; th.Start(); } catch { }; } /// <summary> /// 調用這個方法時把相關內容打印到文本框中 /// </summary> /// <param name="str"></param> void ShowMsg(string str) { txtRecive.AppendText(str + "\r\n"); } //創(chuàng)建一個dictionary集合用來存儲連入的端口號,以ip名為鍵,socket為值 Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>(); void Listen() { while (true) { try { //負責監(jiān)聽的socket在接收到客戶端的連接之后 創(chuàng)建一個負責通信的socket來接收 socketSend = socketListen.Accept(); //如果接收成功 就把發(fā)送端的地址顯現(xiàn)出來 ShowMsg(socketSend.RemoteEndPoint.ToString() + "連接成功!"); dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend); //將連入的ip加入listbox里面 pointList.Items.Add(socketSend.RemoteEndPoint.ToString()); //一直接收客戶端發(fā)來的信息 //需要開啟一個新線程 Thread th = new Thread(Recive); th.IsBackground = true; th.Start(); } catch { }; } } Socket socketSend; /// <summary> /// 接收客戶端發(fā)來的信息 /// </summary> void Recive() { while (true) { try { byte[] buffer = new byte[1024 * 1024 * 5]; int r = socketSend.Receive(buffer); if (r == 0) { break; } string reciveTxt = Encoding.UTF8.GetString(buffer, 0, r); ShowMsg(socketSend.RemoteEndPoint + ":" + reciveTxt); } catch { MessageBox.Show("對方關閉了連接"); break; } } } private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; } /// <summary> /// 發(fā)送文本框中的信息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSend_Click(object sender, EventArgs e) { string str = txtSend.Text; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str); //創(chuàng)建一個list泛型集合裝進buffer數(shù)組,這樣可以在字節(jié)前面加個我們規(guī)定的協(xié)議 //比如說這里0為發(fā)送文本消息,1為發(fā)送文件 List<byte> list = new List<byte>(); //首先這里先把0添加進去,放在第一位,發(fā)過去之后再由接收端判斷是什么文件,那邊再解析 list.Add(0); list.AddRange(buffer); //再把集合轉化成字節(jié)數(shù)組,list集合里裝的是什么類型的數(shù)組,那返回的就是什么類型的數(shù)組 byte[] newBuffer = list.ToArray(); //得到listbox里面選中的ip作為鍵,在dictionary里面找出對應的端口號,發(fā)送信息 //剛剛試了一下,如果沒選的話,返回空,系統(tǒng)拋異常 try { string ip = pointList.SelectedItem.ToString(); dicSocket[ip].Send(newBuffer); } catch { MessageBox.Show("請選擇要發(fā)送的ip"); } //socketSend.Send(buffer); } private void button1_Click(object sender, EventArgs e) { //打開選擇文件對話框 OpenFileDialog ofd = new OpenFileDialog(); //對話框名字 ofd.Title = "請選擇你的文件"; //設定彈出的初始文件夾路徑 ofd.InitialDirectory = @"F:\程序測試文件夾"; //設定好要選擇的文件類型 ofd.Filter = "所有文件|*.*"; //彈出對話框 ofd.ShowDialog(); //獲得文件所選文件的全路徑 string path = ofd.FileName; //把這個全路徑先放進文本框里 txtPath.Text = path; } private void btnSendFile_Click(object sender, EventArgs e) { //創(chuàng)建一個string類型的路徑來存已經(jīng)選好路徑的文本框里的內容 string path = txtPath.Text; //用文件流來操作文件 using (FileStream fsRead = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read)) { //創(chuàng)建字節(jié)數(shù)組并規(guī)定單次接收長度 byte[] buffer = new byte[1024 * 1024 * 5]; //按照規(guī)定的方式讀取并且接收他的單次實際讀取到的長度 int r = fsRead.Read(buffer, 0, buffer.Length); List<byte> list = new List<byte>(); //同樣方法,標記 1,為文件 list.Add(1); list.AddRange(buffer); byte[] newBuffer = list.ToArray(); dicSocket[pointList.SelectedItem.ToString()].Send(newBuffer, 0, r + 1,SocketFlags.None); } } } }

客戶端:
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 客戶端 { public partial class Form2 : Form { public Form2() { InitializeComponent(); } Socket socketLink; private void btnLink_Click(object sender, EventArgs e) { try { socketLink = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ip = IPAddress.Parse(txtIP.Text); IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPoint.Text)); socketLink.Connect(point); ShowMsg("連接成功!"); Thread th = new Thread(Recive); th.IsBackground = true; th.Start(); } catch { }; } /// <summary> /// 傳入需要顯示在文本框中的內容 /// </summary> /// <param name="str"></param> void ShowMsg(string str) { txtRecive.AppendText(str + "\r\n"); } void Recive() { while (true) { try { //設定一個字節(jié)數(shù)組,并規(guī)定它的長度 byte[] buffer = new byte[1024 * 1024 * 5]; //接收通過socketLink傳過來的字節(jié),存進buffer里,并獲取這個字節(jié)數(shù)組的長度 int r = socketLink.Receive(buffer); //獲取這個字節(jié)數(shù)組第一位的數(shù)字,就是我們規(guī)定好的協(xié)議,來判斷發(fā)過來的是消息還是文件 int n = buffer[0]; if (r == 0) { break; } //如果n==0的話就說明發(fā)過來的是文字消息 if (n == 0) { string reciveTxt = Encoding.UTF8.GetString(buffer, 1, r - 1); ShowMsg(socketLink.RemoteEndPoint + ":" + reciveTxt); } else if (n == 1) { //彈出保存文件的對話框,對接收來的字節(jié)數(shù)組進行保存 SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "請選擇你要保存的路徑"; sfd.InitialDirectory = @"F:\程序測試文件夾"; sfd.Filter = "所有文件|*.*"; //由于版本問題,這里要加this才會彈出保存文件的對話框 sfd.ShowDialog(this); string path = sfd.FileName; using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write)) { fsWrite.Write(buffer, 1, r - 1); } ShowMsg("保存成功"); } } catch { MessageBox.Show("服務器已關閉"); break; } } } /// <summary> /// 在程序啟動時 /// 不讓程序報異常:關于子線程持續(xù)調用主線程的內容,跳過 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form2_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; } /// <summary> /// 點擊按鈕發(fā)送文本框里的信息給socket通訊 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSend_Click(object sender, EventArgs e) { string str = txtSend.Text; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str); socketLink.Send(buffer); } } }


浙公網(wǎng)安備 33010602011771號