C#基于Socket的TCP通信實(shí)現(xiàn)聊天室案例
本文實(shí)例為大家分享了C#基于Socket的TCP通信實(shí)現(xiàn)聊天室的具體代碼,供大家參考,具體內(nèi)容如下
一、Socket(套接字)通信概念
套接字(socket)是通信的基石,用于描述IP地址和端口,是一個(gè)通信鏈的句柄,可以用來(lái)實(shí)現(xiàn)不同虛擬機(jī)或不同計(jì)算機(jī)之間的通信,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元。它是網(wǎng)絡(luò)通信過(guò)程中端點(diǎn)的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機(jī)的IP地址,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機(jī)的IP地址,遠(yuǎn)地進(jìn)程的協(xié)議端口。
應(yīng)用層通過(guò)傳輸層進(jìn)行數(shù)據(jù)通信時(shí),TCP會(huì)遇到同時(shí)為多個(gè)應(yīng)用程序進(jìn)程提供并發(fā)服務(wù)的問(wèn)題。多個(gè)TCP連接或多個(gè)應(yīng)用程序進(jìn)程可能需要通過(guò)同一個(gè) TCP協(xié)議端口傳輸數(shù)據(jù)。為了區(qū)別不同的應(yīng)用程序進(jìn)程和連接,許多計(jì)算機(jī)操作系統(tǒng)為應(yīng)用程序與TCP/IP協(xié)議交互提供了套接字(Socket)接口。應(yīng) 用層可以和傳輸層通過(guò)Socket接口,區(qū)分來(lái)自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)。
二、建立socket連接
建立Socket連接至少需要一對(duì)套接字,其中一個(gè)運(yùn)行于客戶(hù)端,稱(chēng)為ClientSocket ,另一個(gè)運(yùn)行于服務(wù)器端,稱(chēng)為ServerSocket 。
套接字之間的連接過(guò)程分為三個(gè)步驟:服務(wù)器監(jiān)聽(tīng),客戶(hù)端請(qǐng)求,連接確認(rèn)。
1、服務(wù)器監(jiān)聽(tīng):服務(wù)器端套接字并不定位具體的客戶(hù)端套接字,而是處于等待連接的狀態(tài),實(shí)時(shí)監(jiān)控網(wǎng)絡(luò)狀態(tài),等待客戶(hù)端的連接請(qǐng)求
2、客戶(hù)端請(qǐng)求:指客戶(hù)端的套接字提出連接請(qǐng)求,要連接的目標(biāo)是服務(wù)器端的套接字。為此,客戶(hù)端的套接字必須首先描述它要連接的服務(wù)器的套接字,指出服務(wù)器端套接字的地址和端口號(hào),然后就向服務(wù)器端套接字提出連接請(qǐng)求。
3、連接確認(rèn):當(dāng)服務(wù)器端套接字監(jiān)聽(tīng)到或者說(shuō)接收到客戶(hù)端套接字的連接請(qǐng)求時(shí),就響應(yīng)客戶(hù)端套接字的請(qǐng)求,建立一個(gè)新的線程,把服務(wù)器端套接字的描述發(fā)給客戶(hù) 端,一旦客戶(hù)端確認(rèn)了此描述,雙方就正式建立連接。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽(tīng)狀態(tài),繼續(xù)接收其他客戶(hù)端套接字的連接請(qǐng)求。
三、SOCKET連接與TCP連接
創(chuàng)建Socket連接時(shí),可以指定使用的傳輸層協(xié)議,Socket可以支持不同的傳輸層協(xié)議(TCP或UDP),當(dāng)使用TCP協(xié)議進(jìn)行連接時(shí),該Socket連接就是一個(gè)TCP連接。
socket通信:分為同步和異步通信,通信兩端分別為客戶(hù)端(Client)和服務(wù)器(Server),,本文簡(jiǎn)單介紹一下同步通信及案例
聊天室案例 服務(wù)端
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; using System.Net; using System.Net.Sockets; using System.Threading; ? namespace 服務(wù)器 { ? ? public partial class Form1 : Form ? ? { ? ? ? ? public Form1() ? ? ? ? { ? ? ? ? ? ? InitializeComponent(); ? ? ? ? ? ? //在多線程編程中,如果需要使用大到主線程需要進(jìn)行檢查取消 ? ? ? ? ? ? CheckForIllegalCrossThreadCalls = false; ? ? ? ? } ? ? ? ? IDictionary<string, Socket> clientList = new Dictionary<string, Socket>(); ? ? ? ? ? ? ? ? private void button1_Click(object sender, EventArgs e) ? ? ? ? { ? ? ? ? ? ? Thread th = new Thread(StartSever); ? ? ? ? ? ? th.IsBackground = true; ? ? ? ? ? ? th.Start(); ? ? ? ? } ? ? ? ? void StartSever() ? ? ? ? { ? ? ? ? ? ? //1.創(chuàng)建服務(wù)器端電話 ? ? ? ? ? ? Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); ? ? ? ? ? ? //2.創(chuàng)建手機(jī)卡 ? ? ? ? ? ? IPAddress ip = IPAddress.Parse(txtIP.Text); ? ? ? ? ? ? //把ip和端口轉(zhuǎn)化為IPEndPoint實(shí)例 ? ? ? ? ? ? IPEndPoint endpoint = new IPEndPoint(ip, int.Parse(txtPort.Text)); ? ? ? ? ? ? //3.將電話卡插入到電話中,綁定端口 ? ? ? ? ? ? server.Bind(endpoint); ? ? ? ? ? ? //4.開(kāi)始監(jiān)聽(tīng)電話 ? ? ? ? ? ? server.Listen(20); ? ? ? ? ? ? listMsg.Items.Add("服務(wù)器已成功開(kāi)啟"); ? ? ? ? ? ? //5.等待接電話 ? ? ? ? ? ? while (true) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? //接收接入的一個(gè)客戶(hù)端 ? ? ? ? ? ? ? ? Socket connectClient = server.Accept(); ? ? ? ? ? ? ? ? if (connectClient != null) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? string infor = connectClient.RemoteEndPoint.ToString(); ? ? ? ? ? ? ? ? ? ? clientList.Add(infor, connectClient); ? ? ? ? ? ? ? ? ? ? listMsg.Items.Add(infor + "加入服務(wù)器"); ? ? ? ? ? ? ? ? ? ? string msg =infor+"已成功進(jìn)入聊天室"; ? ? ? ? ? ? ? ? ? ? SendMsg(msg); ? ? ? ? ? ? ? ? ? ? Thread thread = new Thread(ReciveMsg); ? ? ? ? ? ? ? ? ? ? thread.IsBackground = true; ? ? ? ? ? ? ? ? ? ? thread.Start(connectClient); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? void ReciveMsg(object o) ? ? ? ? { ? ? ? ? ? ? Socket client = o as Socket; ? ? ? ? ? ? while (true) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? try ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? byte[] arrMsg = new byte[1024 * 1024]; ? ? ? ? ? ? ? ? ? ? int length = client.Receive(arrMsg); ? ? ? ? ? ? ? ? ? ? if (length > 0) ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? string recMsg = Encoding.UTF8.GetString(arrMsg, 0, length); ? ? ? ? ? ? ? ? ? ? ? ? IPEndPoint endpoint = client.RemoteEndPoint as IPEndPoint; ? ? ? ? ? ? ? ? ? ? ? ? listMsg.Items.Add(DateTime.Now + "[" + endpoint.Port.ToString() + "]" + recMsg); ? ? ? ? ? ? ? ? ? ? ? ? SendMsg("[" + endpoint.Port.ToString() + "]" + recMsg); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? catch (Exception) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? client.Close(); ? ? ? ? ? ? ? ? ? ? clientList.Remove(client.RemoteEndPoint.ToString()); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? private void label1_Click(object sender, EventArgs e) ? ? ? ? { ? ? ? ? ? ? string ip = IPAddress.Any.ToString(); ? ? ? ? ? ? txtIP.Text = ip; ? ? ? ? } ? ? ? ? void SendMsg(string str) ? ? ? ? { ? ? ? ? ? ? foreach (var item in clientList) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? byte[] arrMsg = Encoding.UTF8.GetBytes(str); ? ? ? ? ? ? ? ? item.Value.Send(arrMsg); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? private void button2_Click(object sender, EventArgs e) ? ? ? ? { ? ? ? ? ? ? if (txtMsg.Text!="") ? ? ? ? ? ? { ? ? ? ? ? ? ? ? SendMsg(txtMsg.Text); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
客戶(hù)端
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; using System.Net; using System.Net.Sockets; using System.Threading; namespace 服務(wù)器2._12 { ? ? public partial class Form1 : Form ? ? { ? ? ? ? public Form1() ? ? ? ? { ? ? ? ? ? ? InitializeComponent(); ? ? ? ? ? ? CheckForIllegalCrossThreadCalls = false; ? ? ? ? } ? ? ? ? Socket Client; ? ? ? ? private void button1_Click(object sender, EventArgs e) ? ? ? ? { ? ? ? ? ? ? //創(chuàng)建服務(wù)器端電話 ? ? ? ? ? ? Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); ? ? ? ? ? ? //創(chuàng)建手機(jī)卡 ? ? ? ? ? ? IPAddress ip = IPAddress.Parse(txtIP.Text); ? ? ? ? ? ? IPEndPoint endinput = new IPEndPoint(ip, int.Parse(txtport.Text)); ? ? ? ? ? ? Client.Connect(endinput); ? ? ? ? ? ? Thread th = new Thread(ReciveMsg); ? ? ? ? ? ? th.IsBackground = true; ? ? ? ? ? ? th.Start(Client); ? ? ? ? } ? ? ? ? void ReciveMsg(object o) ? ? ? ? { ? ? ? ? ? ? Socket client = o as Socket; ? ? ? ? ? ? //5.等待接電話 ? ? ? ? ? ? while (true) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? byte[] arrlist = new byte[1024*1024]; ? ? ? ? ? ? ? ? int length = client.Receive(arrlist); ? ? ? ? ? ? ? ? string msg = DateTime.Now + Encoding.UTF8.GetString(arrlist,0,length); ? ? ? ? ? ? ? ? listmsg.Items.Add(msg); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? private void button2_Click(object sender, EventArgs e) ? ? ? ? { ? ? ? ? ? ? if (txtinput.Text!=null) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? SendMsg(txtinput.Text); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? void SendMsg(string msg) ? ? ? ? { ? ? ? ? ? ? byte[] arrMsg = Encoding.UTF8.GetBytes(msg); ? ? ? ? ? ? Client.Send(arrMsg); ? ? ? ? } ? ? } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MessageBox的Buttons和三級(jí)聯(lián)動(dòng)效果
這篇文章主要介紹了MessageBox的Buttons和三級(jí)聯(lián)動(dòng)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11C#中判斷本地系統(tǒng)的網(wǎng)絡(luò)連接狀態(tài)的方法
C#中一般通過(guò)InternetGetConnectedState函數(shù)返回本地系統(tǒng)的網(wǎng)絡(luò)連接狀態(tài),下面簡(jiǎn)單介紹下,需要的朋友可以參考下2013-10-10C# 靜態(tài)構(gòu)造函數(shù)使用總結(jié)
今天花了一些時(shí)間把靜態(tài)構(gòu)造函數(shù)的用法總結(jié)了一下,希望高手們指點(diǎn)。謝謝2013-03-03Entity Framework主從表數(shù)據(jù)加載方式
這篇文章介紹了Entity Framework主從表數(shù)據(jù)加載方式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06淺析.NET中AsyncLocal的實(shí)現(xiàn)原理
這篇文章主要為大家詳細(xì)介紹了.NET中AsyncLocal的具體實(shí)現(xiàn)原理,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,如果有講得不清晰或不準(zhǔn)確的地方,還望指出2023-08-08datagridview實(shí)現(xiàn)手動(dòng)添加行數(shù)據(jù)
這篇文章主要介紹了datagridview實(shí)現(xiàn)手動(dòng)添加行數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Unity3D Shader實(shí)現(xiàn)鏡子效果
這篇文章主要為大家詳細(xì)介紹了Unity3D Shader實(shí)現(xiàn)鏡子效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05C#字典Dictionary的用法說(shuō)明(注重性能版)
這篇文章主要介紹了C#字典Dictionary的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(3) 文本消息和圖文消息應(yīng)答
這篇文章主要為大家詳細(xì)介紹了C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用第二篇,微信文本消息和圖文消息的應(yīng)答,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06