c#基于WinForm的Socket實(shí)現(xiàn)簡(jiǎn)單的聊天室 IM
1:什么是Socket
所謂套接字(Socket),就是對(duì)網(wǎng)絡(luò)中不同主機(jī)上的應(yīng)用進(jìn)程之間進(jìn)行雙向通信的端點(diǎn)的抽象。
一個(gè)套接字就是網(wǎng)絡(luò)上進(jìn)程通信的一端,提供了應(yīng)用層進(jìn)程利用網(wǎng)絡(luò)協(xié)議交換數(shù)據(jù)的機(jī)制。
從所處的地位來講,套接字上聯(lián)應(yīng)用進(jìn)程,下聯(lián)網(wǎng)絡(luò)協(xié)議棧,是應(yīng)用程序通過網(wǎng)絡(luò)協(xié)議進(jìn)行通信的接口,是應(yīng)用程序與網(wǎng)絡(luò)協(xié)議根進(jìn)行交互的接口。
2:客服端和服務(wù)端的通信簡(jiǎn)單流程
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("連接失敗!或者ip,端口參數(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) { //退到一個(gè)客服端的時(shí)候 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ā)送的一個(gè)用戶 /// </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("請(qǐng)先選擇左側(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("暫時(shí)沒有客服端登錄!"); return; } var sendMsg = ServiceSockertHelper.GetSendMsgByte(getmSg, ChatTypeInfoEnum.StringEnum); foreach (var usersocket in userinfo) { usersocket.ChatSocket?.Send(sendMsg); } } /// <summary> /// 服務(wù)器給發(fā)送震動(dòng) /// </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("請(qǐng)先選擇左側(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";//先初始化一個(gè)默認(rèn)的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("請(qǐng)檢查要連接的服務(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:測(cè)試效果:
6:完整Code GitHUb下載路徑
https://github.com/zrf518/WinformSocketChat.git
7:這個(gè)只是一個(gè)簡(jiǎn)單的聊天練習(xí)Demo,待進(jìn)一步完善(實(shí)現(xiàn)部分功能,傳遞的消息byte[0]為消息的類型,用來判斷是文字,還是圖片等等),歡迎大家指教
以上就是c#基于WinForm的Socket實(shí)現(xiàn)簡(jiǎn)單的聊天室 IM的詳細(xì)內(nèi)容,更多關(guān)于c# WinForm實(shí)現(xiàn)聊天室 IM的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- C#基于Socket實(shí)現(xiàn)簡(jiǎn)單聊天室功能
- ASP.net(C#)實(shí)現(xiàn)簡(jiǎn)易聊天室功能
- C#簡(jiǎn)單聊天室雛形
- C#使用WebSocket實(shí)現(xiàn)聊天室功能
- C#實(shí)現(xiàn)簡(jiǎn)易多人聊天室
- C#使用Socket實(shí)現(xiàn)本地多人聊天室
- C#制作簡(jiǎn)單的多人在線即時(shí)交流聊天室
- 分享一個(gè)C#編寫簡(jiǎn)單的聊天程序(詳細(xì)介紹)
- C#聊天程序服務(wù)端與客戶端完整實(shí)例代碼
- C#基于Socket的TCP通信實(shí)現(xiàn)聊天室案例
相關(guān)文章
C#編程實(shí)現(xiàn)四舍五入、向上及下取整的方法
這篇文章主要介紹了C#編程實(shí)現(xiàn)四舍五入、向上及下取整的方法,涉及C#數(shù)學(xué)運(yùn)算的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11C# Winform中實(shí)現(xiàn)主窗口打開登錄窗口關(guān)閉的方法
這篇文章主要介紹了C# Winform中實(shí)現(xiàn)主窗口打開登錄窗口關(guān)閉的方法,這在需要用戶名密碼的軟件項(xiàng)目中是必用的一個(gè)技巧,要的朋友可以參考下2014-08-08WCF實(shí)現(xiàn)進(jìn)程間管道通信Demo分享
下面小編就為大家分享一篇WCF實(shí)現(xiàn)進(jìn)程間管道通信Demo,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-12-12c# 判斷指定文件是否存在的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了c# 判斷指定文件是否存在的簡(jiǎn)單實(shí)現(xiàn),需要的朋友可以參考下2014-02-02C#基于DBContext(EF)實(shí)現(xiàn)通用增刪改查的REST方法實(shí)例
這篇文章主要介紹了C#基于DBContext(EF)實(shí)現(xiàn)通用增刪改查的REST方法實(shí)例,是C#程序設(shè)計(jì)中非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10C#自定義事件監(jiān)聽實(shí)現(xiàn)方法
這篇文章主要介紹了C#自定義事件監(jiān)聽實(shí)現(xiàn)方法,涉及C#事件監(jiān)聽的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08C#實(shí)現(xiàn)Windows Form調(diào)用R進(jìn)行繪圖與顯示的方法
眾所周知R軟件功能非常強(qiáng)大,可以很好的進(jìn)行各類統(tǒng)計(jì),并能輸出圖形。下面介紹一種R語言和C#進(jìn)行通信的方法,并將R繪圖結(jié)果顯示到WinForm UI界面上的方法,文中介紹的很詳細(xì),需要的朋友可以參考下。2017-02-02