c#基于WinForm的Socket實現(xiàn)簡單的聊天室 IM
1:什么是Socket
所謂套接字(Socket),就是對網(wǎng)絡(luò)中不同主機上的應(yīng)用進程之間進行雙向通信的端點的抽象。
一個套接字就是網(wǎng)絡(luò)上進程通信的一端,提供了應(yīng)用層進程利用網(wǎng)絡(luò)協(xié)議交換數(shù)據(jù)的機制。
從所處的地位來講,套接字上聯(lián)應(yīng)用進程,下聯(lián)網(wǎng)絡(luò)協(xié)議棧,是應(yīng)用程序通過網(wǎng)絡(luò)協(xié)議進行通信的接口,是應(yīng)用程序與網(wǎng)絡(luò)協(xié)議根進行交互的接口。
2:客服端和服務(wù)端的通信簡單流程
3:服務(wù)端Code:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ChartService { using System.Net; using System.Net.Sockets; using System.Threading; using ChatCommoms; using ChatModels; public partial class ServiceForm : Form { Socket _socket; private static List<ChatUserInfo> userinfo = new List<ChatUserInfo>(); public ServiceForm() { InitializeComponent(); } private void btnServicStart_Click(object sender, EventArgs e) { try { string ip = textBox_ip.Text.Trim(); string port = textBox_port.Text.Trim(); if (string.IsNullOrWhiteSpace(ip) || string.IsNullOrWhiteSpace(port)) { MessageBox.Show("IP與端口不可以為空!"); } ServiceStartAccept(ip, int.Parse(port)); } catch (Exception) { MessageBox.Show("連接失?。』蛘遡p,端口參數(shù)異常"); } } public void ServiceStartAccept(string ip, int port) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint endport = new IPEndPoint(IPAddress.Parse(ip), port); socket.Bind(endport); socket.Listen(10); Thread thread = new Thread(Recevice); thread.IsBackground = true; thread.Start(socket); textboMsg.AppendText("服務(wù)開啟ok..."); } /// <summary> /// 開啟接聽服務(wù) /// </summary> /// <param name="obj"></param> private void Recevice(object obj) { var socket = obj as Socket; while (true) { string remoteEpInfo = string.Empty; try { Socket txSocket = socket.Accept(); _socket = txSocket; if (txSocket.Connected) { remoteEpInfo = txSocket.RemoteEndPoint.ToString(); textboMsg.AppendText($"\r\n{remoteEpInfo}:連接上線了..."); var clientUser = new ChatUserInfo { UserID = Guid.NewGuid().ToString(), ChatUid = remoteEpInfo, ChatSocket = txSocket }; userinfo.Add(clientUser); listBoxCoustomerList.Items.Add(new ChatUserInfoBase { UserID = clientUser.UserID, ChatUid = clientUser.ChatUid }); listBoxCoustomerList.DisplayMember = "ChatUid"; listBoxCoustomerList.ValueMember = "UserID"; ReceseMsgGoing(txSocket, remoteEpInfo); } else { if (userinfo.Count > 0) { userinfo.Remove(userinfo.Where(c => c.ChatUid == remoteEpInfo).FirstOrDefault()); //移除下拉框?qū)τ诘膕ocket或者叫用戶 } break; } } catch (Exception) { if (userinfo.Count > 0) { userinfo.Remove(userinfo.Where(c => c.ChatUid == remoteEpInfo).FirstOrDefault()); //移除下拉框?qū)τ诘膕ocket或者叫用戶 } } } } /// <summary> /// 接受來自客服端發(fā)來的消息 /// </summary> /// <param name="txSocket"></param> /// <param name="remoteEpInfo"></param> private void ReceseMsgGoing(Socket txSocket, string remoteEpInfo) { //退到一個客服端的時候 int getlength = txSocket.Receive(recesiveByte); 有拋異常 Thread thread = new Thread(() => { while (true) { try { byte[] recesiveByte = new byte[1024 * 1024 * 4]; int getlength = txSocket.Receive(recesiveByte); if (getlength <= 0) { break; } var getType = recesiveByte[0].ToString(); string getmsg = Encoding.UTF8.GetString(recesiveByte, 1, getlength - 1); ShowMsg(remoteEpInfo, getType, getmsg); } catch (Exception) { //string userid = userinfo.FirstOrDefault(c => c.ChatUid == remoteEpInfo)?.ChatUid; listBoxCoustomerList.Items.Remove(remoteEpInfo); userinfo.Remove(userinfo.FirstOrDefault(c => c.ChatUid == remoteEpInfo));//從集合中移除斷開的socket listBoxCoustomerList.DataSource = userinfo;//重新綁定下來的信息 listBoxCoustomerList.DisplayMember = "ChatUid"; listBoxCoustomerList.ValueMember = "UserID"; txSocket.Dispose(); txSocket.Close(); } } }); thread.IsBackground = true; thread.Start(); } private void ShowMsg(string remoteEpInfo, string getType, string getmsg) { textboMsg.AppendText($"\r\n{remoteEpInfo}:消息類型:{getType}:{getmsg}"); } private void Form1_Load(object sender, EventArgs e) { CheckForIllegalCrossThreadCalls = false; this.textBox_ip.Text = "192.168.1.101";//初始值 this.textBox_port.Text = "50000"; } /// <summary> /// 服務(wù)器發(fā)送消息,可以先選擇要發(fā)送的一個用戶 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendMsg_Click(object sender, EventArgs e) { var getmSg = textBoxSendMsg.Text.Trim(); if (string.IsNullOrWhiteSpace(getmSg)) { MessageBox.Show("要發(fā)送的消息不可以為空", "注意"); return; } var obj = listBoxCoustomerList.SelectedItem; int getindex = listBoxCoustomerList.SelectedIndex; if (obj == null || getindex == -1) { MessageBox.Show("請先選擇左側(cè)用戶的用戶"); return; } var getChoseUser = obj as ChatUserInfoBase; var sendMsg = ServiceSockertHelper.GetSendMsgByte(getmSg, ChatTypeInfoEnum.StringEnum); userinfo.FirstOrDefault(c => c.ChatUid == getChoseUser.ChatUid)?.ChatSocket?.Send(sendMsg); } /// <summary> /// 給所有登錄的用戶發(fā)送消息,群發(fā)了 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { var getmSg = textBoxSendMsg.Text.Trim(); if (string.IsNullOrWhiteSpace(getmSg)) { MessageBox.Show("要發(fā)送的消息不可以為空", "注意"); return; } if (userinfo.Count <= 0) { MessageBox.Show("暫時沒有客服端登錄!"); return; } var sendMsg = ServiceSockertHelper.GetSendMsgByte(getmSg, ChatTypeInfoEnum.StringEnum); foreach (var usersocket in userinfo) { usersocket.ChatSocket?.Send(sendMsg); } } /// <summary> /// 服務(wù)器給發(fā)送震動 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendSnak_Click(object sender, EventArgs e) { var obj = listBoxCoustomerList.SelectedItem; int getindex = listBoxCoustomerList.SelectedIndex; if (obj == null || getindex == -1) { MessageBox.Show("請先選擇左側(cè)用戶的用戶"); return; } var getChoseUser = obj as ChatUserInfoBase; byte[] sendMsgByte = ServiceSockertHelper.GetSendMsgByte("", ChatTypeInfoEnum.Snake); userinfo.FirstOrDefault(c => c.ChatUid == getChoseUser.ChatUid)?.ChatSocket.Send(sendMsgByte); } } }
4:客服端Code:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ChatClient { using ChatCommoms; using System.Net; using System.Net.Sockets; using System.Threading; public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { CheckForIllegalCrossThreadCalls = false; this.textBoxIp.Text = "192.168.1.101";//先初始化一個默認的ip等 this.textBoxPort.Text = "50000"; } Socket clientSocket; /// <summary> /// 客服端連接到服務(wù)器 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnServicStart_Click(object sender, EventArgs e) { try { var ipstr = textBoxIp.Text.Trim(); var portstr = textBoxPort.Text.Trim(); if (string.IsNullOrWhiteSpace(ipstr) || string.IsNullOrWhiteSpace(portstr)) { MessageBox.Show("要連接的服務(wù)器ip和端口都不可以為空!"); return; } clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.Connect(IPAddress.Parse(ipstr), int.Parse(portstr)); labelStatus.Text = "連接到服務(wù)器成功...!"; ReseviceMsg(clientSocket); } catch (Exception) { MessageBox.Show("請檢查要連接的服務(wù)器的參數(shù)"); } } private void ReseviceMsg(Socket clientSocket) { Thread thread = new Thread(() => { while (true) { try { Byte[] byteContainer = new Byte[1024 * 1024 * 4]; int getlength = clientSocket.Receive(byteContainer); if (getlength <= 0) { break; } var getType = byteContainer[0].ToString(); string getmsg = Encoding.UTF8.GetString(byteContainer, 1, getlength - 1); GetMsgFomServer(getType, getmsg); } catch (Exception ex) { } } }); thread.IsBackground = true; thread.Start(); } private void GetMsgFomServer(string strType, string msg) { this.textboMsg.AppendText($"\r\n類型:{strType};{msg}"); } /// <summary> /// 文字消息的發(fā)送 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendMsg_Click(object sender, EventArgs e) { var msg = textBoxSendMsg.Text.Trim(); var sendMsg = ServiceSockertHelper.GetSendMsgByte(msg, ChatModels.ChatTypeInfoEnum.StringEnum); int sendMsgLength = clientSocket.Send(sendMsg); } } }
5:測試效果:
6:完整Code GitHUb下載路徑
https://github.com/zrf518/WinformSocketChat.git
7:這個只是一個簡單的聊天練習Demo,待進一步完善(實現(xiàn)部分功能,傳遞的消息byte[0]為消息的類型,用來判斷是文字,還是圖片等等),歡迎大家指教
以上就是c#基于WinForm的Socket實現(xiàn)簡單的聊天室 IM的詳細內(nèi)容,更多關(guān)于c# WinForm實現(xiàn)聊天室 IM的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C# Winform中實現(xiàn)主窗口打開登錄窗口關(guān)閉的方法
這篇文章主要介紹了C# Winform中實現(xiàn)主窗口打開登錄窗口關(guān)閉的方法,這在需要用戶名密碼的軟件項目中是必用的一個技巧,要的朋友可以參考下2014-08-08C#基于DBContext(EF)實現(xiàn)通用增刪改查的REST方法實例
這篇文章主要介紹了C#基于DBContext(EF)實現(xiàn)通用增刪改查的REST方法實例,是C#程序設(shè)計中非常實用的技巧,需要的朋友可以參考下2014-10-10C#實現(xiàn)Windows Form調(diào)用R進行繪圖與顯示的方法
眾所周知R軟件功能非常強大,可以很好的進行各類統(tǒng)計,并能輸出圖形。下面介紹一種R語言和C#進行通信的方法,并將R繪圖結(jié)果顯示到WinForm UI界面上的方法,文中介紹的很詳細,需要的朋友可以參考下。2017-02-02