C#使用Socket實(shí)現(xiàn)服務(wù)器與多個(gè)客戶端通信(簡(jiǎn)單的聊天系統(tǒng))
擴(kuò)展:
由于server端是存儲(chǔ)了所有server與client的連接對(duì)象,因此我們是可以基于此demo的基礎(chǔ)上實(shí)現(xiàn)聊天系統(tǒng):
* 每當(dāng)一個(gè)與用戶發(fā)言時(shí),是由server接收到的某個(gè)用戶的發(fā)言信息的,此時(shí)服務(wù)器端可以通過(guò)循環(huán)發(fā)送該用戶發(fā)送的信息給每個(gè)已經(jīng)連接連接的用戶(排除發(fā)送者)。
Server端代碼:
class Program
{
//創(chuàng)建一個(gè)和客戶端通信的套接字
static Socket SocketWatch = null;
//定義一個(gè)集合,存儲(chǔ)客戶端信息
static Dictionary<string, Socket> ClientConnectionItems = new Dictionary<string, Socket> { };
static void Main(string[] args)
{
//端口號(hào)(用來(lái)監(jiān)聽(tīng)的)
int port = 6000;
//string host = "127.0.0.1";
//IPAddress ip = IPAddress.Parse(host);
IPAddress ip = IPAddress.Any;
//將IP地址和端口號(hào)綁定到網(wǎng)絡(luò)節(jié)點(diǎn)point上
IPEndPoint ipe = new IPEndPoint(ip, port);
//定義一個(gè)套接字用于監(jiān)聽(tīng)客戶端發(fā)來(lái)的消息,包含三個(gè)參數(shù)(IP4尋址協(xié)議,流式連接,Tcp協(xié)議)
SocketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//監(jiān)聽(tīng)綁定的網(wǎng)絡(luò)節(jié)點(diǎn)
SocketWatch.Bind(ipe);
//將套接字的監(jiān)聽(tīng)隊(duì)列長(zhǎng)度限制為20
SocketWatch.Listen(20);
//負(fù)責(zé)監(jiān)聽(tīng)客戶端的線程:創(chuàng)建一個(gè)監(jiān)聽(tīng)線程
Thread threadwatch = new Thread(WatchConnecting);
//將窗體線程設(shè)置為與后臺(tái)同步,隨著主線程結(jié)束而結(jié)束
threadwatch.IsBackground = true;
//啟動(dòng)線程
threadwatch.Start();
Console.WriteLine("開(kāi)啟監(jiān)聽(tīng)......");
Console.WriteLine("點(diǎn)擊輸入任意數(shù)據(jù)回車退出程序......");
Console.ReadKey();
SocketWatch.Close();
//Socket serverSocket = null;
//int i=1;
//while (true)
//{
// //receive message
// serverSocket = SocketWatch.Accept();
// Console.WriteLine("連接已經(jīng)建立!");
// string recStr = "";
// byte[] recByte = new byte[4096];
// int bytes = serverSocket.Receive(recByte, recByte.Length, 0);
// //recStr += Encoding.ASCII.GetString(recByte, 0, bytes);
// recStr += Encoding.GetEncoding("utf-8").GetString(recByte, 0, bytes);
// //send message
// Console.WriteLine(recStr);
// Console.Write("請(qǐng)輸入內(nèi)容:");
// string sendStr = Console.ReadLine();
// //byte[] sendByte = Encoding.ASCII.GetBytes(sendStr);
// byte[] sendByte = Encoding.GetEncoding("utf-8").GetBytes(sendStr);
// //Thread.Sleep(4000);
// serverSocket.Send(sendByte, sendByte.Length, 0);
// serverSocket.Close();
// if (i >= 100)
// {
// break;
// }
// i++;
//}
//sSocket.Close();
//Console.WriteLine("連接關(guān)閉!");
//Console.ReadLine();
}
//監(jiān)聽(tīng)客戶端發(fā)來(lái)的請(qǐng)求
static void WatchConnecting()
{
Socket connection = null;
//持續(xù)不斷監(jiān)聽(tīng)客戶端發(fā)來(lái)的請(qǐng)求
while (true)
{
try
{
connection = SocketWatch.Accept();
}
catch (Exception ex)
{
//提示套接字監(jiān)聽(tīng)異常
Console.WriteLine(ex.Message);
break;
}
//客戶端網(wǎng)絡(luò)結(jié)點(diǎn)號(hào)
string remoteEndPoint = connection.RemoteEndPoint.ToString();
//添加客戶端信息
ClientConnectionItems.Add(remoteEndPoint, connection);
//顯示與客戶端連接情況
Console.WriteLine("\r\n[客戶端\"" + remoteEndPoint + "\"建立連接成功! 客戶端數(shù)量:" + ClientConnectionItems .Count+ "]");
//獲取客戶端的IP和端口號(hào)
IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address;
int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port;
//讓客戶顯示"連接成功的"的信息
string sendmsg = "[" + "本地IP:" + clientIP + " 本地端口:" + clientPort.ToString() + " 連接服務(wù)端成功!]";
byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg);
connection.Send(arrSendMsg);
//創(chuàng)建一個(gè)通信線程
Thread thread = new Thread(recv);
//設(shè)置為后臺(tái)線程,隨著主線程退出而退出
thread.IsBackground = true;
//啟動(dòng)線程
thread.Start(connection);
}
}
/// <summary>
/// 接收客戶端發(fā)來(lái)的信息,客戶端套接字對(duì)象
/// </summary>
/// <param name="socketclientpara"></param>
static void recv(object socketclientpara)
{
Socket socketServer = socketclientpara as Socket;
while (true)
{
//創(chuàng)建一個(gè)內(nèi)存緩沖區(qū),其大小為1024*1024字節(jié) 即1M
byte[] arrServerRecMsg = new byte[1024 * 1024];
//將接收到的信息存入到內(nèi)存緩沖區(qū),并返回其字節(jié)數(shù)組的長(zhǎng)度
try
{
int length = socketServer.Receive(arrServerRecMsg);
//將機(jī)器接受到的字節(jié)數(shù)組轉(zhuǎn)換為人可以讀懂的字符串
string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);
//將發(fā)送的字符串信息附加到文本框txtMsg上
Console.WriteLine("\r\n[客戶端:" + socketServer.RemoteEndPoint + " 時(shí)間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")+ "]\r\n" + strSRecMsg);
//Thread.Sleep(3000);
//socketServer.Send(Encoding.UTF8.GetBytes("[" + socketServer.RemoteEndPoint + "]:"+strSRecMsg));
//發(fā)送客戶端數(shù)據(jù)
if (ClientConnectionItems.Count > 0)
{
foreach (var socketTemp in ClientConnectionItems)
{
socketTemp.Value.Send(Encoding.UTF8.GetBytes("[" + socketServer.RemoteEndPoint + "]:" + strSRecMsg));
}
}
}
catch (Exception)
{
ClientConnectionItems.Remove(socketServer.RemoteEndPoint.ToString());
//提示套接字監(jiān)聽(tīng)異常
Console.WriteLine("\r\n[客戶端\"" + socketServer.RemoteEndPoint + "\"已經(jīng)中斷連接! 客戶端數(shù)量:" + ClientConnectionItems.Count+"]");
//關(guān)閉之前accept出來(lái)的和客戶端進(jìn)行通信的套接字
socketServer.Close();
break;
}
}
}
}
Client端代碼:
class Program
{
//創(chuàng)建1個(gè)客戶端套接字和1個(gè)負(fù)責(zé)監(jiān)聽(tīng)服務(wù)端請(qǐng)求的線程
static Thread ThreadClient = null;
static Socket SocketClient = null;
static void Main(string[] args)
{
try
{
int port = 6000;
string host = "127.0.0.1";//服務(wù)器端ip地址
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);
//定義一個(gè)套接字監(jiān)聽(tīng)
SocketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
//客戶端套接字連接到網(wǎng)絡(luò)節(jié)點(diǎn)上,用的是Connect
SocketClient.Connect(ipe);
}
catch (Exception)
{
Console.WriteLine("連接失?。r\n");
Console.ReadLine();
return;
}
ThreadClient = new Thread(Recv);
ThreadClient.IsBackground = true;
ThreadClient.Start();
Thread.Sleep(1000);
Console.WriteLine("請(qǐng)輸入內(nèi)容<按Enter鍵發(fā)送>:\r\n");
while(true)
{
string sendStr = Console.ReadLine();
ClientSendMsg(sendStr);
}
//int i = 1;
//while (true)
//{
// Console.Write("請(qǐng)輸入內(nèi)容:");
// string sendStr = Console.ReadLine();
// Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// clientSocket.Connect(ipe);
// //send message
// //byte[] sendBytes = Encoding.ASCII.GetBytes(sendStr);
// byte[] sendBytes = Encoding.GetEncoding("utf-8").GetBytes(sendStr);
// //Thread.Sleep(4000);
// clientSocket.Send(sendBytes);
// //receive message
// string recStr = "";
// byte[] recBytes = new byte[4096];
// int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0);
// //recStr += Encoding.ASCII.GetString(recBytes, 0, bytes);
// recStr += Encoding.GetEncoding("utf-8").GetString(recBytes, 0, bytes);
// Console.WriteLine(recStr);
// clientSocket.Close();
// if (i >= 100)
// {
// break;
// }
// i++;
//}
//Console.ReadLine();
//return;
//string result = String.Empty;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
//接收服務(wù)端發(fā)來(lái)信息的方法
public static void Recv()
{
int x = 0;
//持續(xù)監(jiān)聽(tīng)服務(wù)端發(fā)來(lái)的消息
while (true)
{
try
{
//定義一個(gè)1M的內(nèi)存緩沖區(qū),用于臨時(shí)性存儲(chǔ)接收到的消息
byte[] arrRecvmsg = new byte[1024 * 1024];
//將客戶端套接字接收到的數(shù)據(jù)存入內(nèi)存緩沖區(qū),并獲取長(zhǎng)度
int length = SocketClient.Receive(arrRecvmsg);
//將套接字獲取到的字符數(shù)組轉(zhuǎn)換為人可以看懂的字符串
string strRevMsg = Encoding.UTF8.GetString(arrRecvmsg, 0, length);
if (x == 1)
{
Console.WriteLine("\r\n服務(wù)器:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "\r\n" + strRevMsg+"\r\n");
}
else
{
Console.WriteLine(strRevMsg + "\r\n");
x = 1;
}
}
catch (Exception ex)
{
Console.WriteLine("遠(yuǎn)程服務(wù)器已經(jīng)中斷連接!" + ex.Message + "\r\n");
break;
}
}
}
//發(fā)送字符信息到服務(wù)端的方法
public static void ClientSendMsg(string sendMsg)
{
//將輸入的內(nèi)容字符串轉(zhuǎn)換為機(jī)器可以識(shí)別的字節(jié)數(shù)組
byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
//調(diào)用客戶端套接字發(fā)送字節(jié)數(shù)組
SocketClient.Send(arrClientSendMsg);
}
}
測(cè)試結(jié)果:
server端:

client端:



代碼下載地址:C-Socket_jb51.zip
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- C#使用WebSocket實(shí)現(xiàn)聊天室功能
- C#使用Socket實(shí)現(xiàn)本地多人聊天室
- C#基于Socket實(shí)現(xiàn)多人聊天功能
- c#基于WinForm的Socket實(shí)現(xiàn)簡(jiǎn)單的聊天室 IM
- C# Socket編程實(shí)現(xiàn)簡(jiǎn)單的局域網(wǎng)聊天器的示例代碼
- C#使用Socket實(shí)現(xiàn)局域網(wǎng)聊天
- 基于c#用Socket做一個(gè)局域網(wǎng)聊天工具
- 分享一個(gè)C#編寫(xiě)簡(jiǎn)單的聊天程序(詳細(xì)介紹)
- C#制作簡(jiǎn)單的多人在線即時(shí)交流聊天室
- C#用websocket實(shí)現(xiàn)簡(jiǎn)易聊天功能(服務(wù)端)
相關(guān)文章
C#實(shí)現(xiàn)簡(jiǎn)單學(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)簡(jiǎn)單學(xué)生信息管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06
簡(jiǎn)單的excel導(dǎo)入導(dǎo)出示例分享
這篇文章主要介紹了簡(jiǎn)單的excel導(dǎo)入導(dǎo)出示例分享,需要的朋友可以參考下2014-03-03
帶著問(wèn)題讀CLR via C#(筆記一)CLR的執(zhí)行模型
CLR (Common Language Runtime) 是一個(gè)可以由多種編程語(yǔ)言使用的“運(yùn)行時(shí)”。2013-04-04
使用C#實(shí)現(xiàn)在屏幕上畫(huà)圖效果的代碼實(shí)例
本篇文章是對(duì)使用C#在屏幕上畫(huà)圖效果的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C# winform 請(qǐng)求http的實(shí)現(xiàn)(get,post)
本文主要介紹了C# winform 請(qǐng)求http的實(shí)現(xiàn)(get,post),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
C#實(shí)現(xiàn)目錄跳轉(zhuǎn)(TreeView和SplitContainer)的示例代碼
本文主要介紹了C#實(shí)現(xiàn)目錄跳轉(zhuǎn)(TreeView和SplitContainer)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
C#使用linq對(duì)數(shù)組進(jìn)行篩選排序的方法
這篇文章主要介紹了C#使用linq對(duì)數(shù)組進(jìn)行篩選排序的方法,實(shí)例分析了C#實(shí)用linq擴(kuò)展進(jìn)行數(shù)組排序的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04

