C#利用服務(wù)器實(shí)現(xiàn)客戶(hù)端之間通信
先來(lái)講述下我自己對(duì)于整個(gè)Socket通信過(guò)程的理解,畢竟初學(xué),說(shuō)錯(cuò)見(jiàn)諒,知道錯(cuò)了會(huì)改正~
首先在服務(wù)端新建一個(gè)serverSocket,對(duì)其進(jìn)行初始化(一般包含AddressFamily:IP地址類(lèi)型,SocketType:Socket傳輸數(shù)據(jù)方式,ProtoType:傳輸協(xié)議);
接著我們要設(shè)置server端要綁定的IP:port;然后開(kāi)始監(jiān)聽(tīng),并設(shè)置最多同時(shí)監(jiān)聽(tīng)多少個(gè)Client.
這時(shí),服務(wù)端就在等待狀態(tài),直到某一個(gè)Client連接到這個(gè)ip:port上,這時(shí)serverSocket.Accept()工作,獲得這個(gè)連接。(此時(shí)的連接是有地址信息的哦!記得保存)
獲得連接之后,server就可以和這個(gè)Client進(jìn)行通信了,當(dāng)加入第二個(gè)Client(我們稱(chēng)其為ClientB)時(shí),Server接收到ClientB的消息,可以將這個(gè)消息轉(zhuǎn)發(fā)給前一個(gè)Client(我們稱(chēng)其為ClientA),當(dāng)受到ClientA的消息,也可以轉(zhuǎn)發(fā)給ClientB。這樣就實(shí)現(xiàn)了Clients之間的通信了。(重點(diǎn)在保存連接信息?。。?br />
那么現(xiàn)在貼上代碼講解:
Server端代碼
namespace SocketServer
{
class Program
{
private static byte[] result = new byte[1024];
static Socket serverSocket;
private static string client;
private static Socket clientSocket;
//我這里存了兩個(gè)Client,因?yàn)樽约弘娔X開(kāi)了兩個(gè)Client,不會(huì)有多的
//理論上應(yīng)該開(kāi)一個(gè)Socket[]來(lái)保存信息,最好用一個(gè)二元組將client的信息和連接綁定起來(lái)
//這樣就可以實(shí)現(xiàn)斷開(kāi)連接后下次登陸還是可以識(shí)別是這個(gè)Client
private static Socket clientSocketA=null;
private static Socket clientSocketB=null;
static void Main(string[] args)
{
Program.SetPort(8885);
}
private static void SetPort(int port)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");//set ip
serverSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);//initialize
serverSocket.Bind(new IPEndPoint(ip, port));//bind
serverSocket.Listen(10);
//進(jìn)入監(jiān)聽(tīng)狀態(tài)
Console.WriteLine("監(jiān)聽(tīng){0}成功", serverSocket.LocalEndPoint.ToString());
//開(kāi)啟一個(gè)線(xiàn)程來(lái)監(jiān)聽(tīng)客戶(hù)端連接
Thread myThread = new Thread(ListenClientConnect);
myThread.Start();
Console.ReadLine();
}
/// <summary>
/// 監(jiān)聽(tīng)客戶(hù)端連接
/// </summary>
private static void ListenClientConnect()
{
while (true)
{
//Client連接上后 得到這個(gè)連接
clientSocket = serverSocket.Accept();
//這里我因?yàn)橹挥袃蓚€(gè)Client,所以就簡(jiǎn)單寫(xiě)了
if (clientSocketA == null)
{
clientSocketA = clientSocket;
}
else if (clientSocketB == null)
{
clientSocketB = clientSocket;
}
else
{
//當(dāng)其中一個(gè)斷開(kāi)了,又重新連接時(shí),需要再次保存連接
if (clientSocketB.IsBound)
{
clientSocketA = clientSocketB;
clientSocketB = clientSocket;
}
else
{
clientSocketB = clientSocketA;
clientSocketA = clientSocket;
}
}
clientSocket.Send(Encoding.ASCII.GetBytes("say hello"));
//開(kāi)個(gè)線(xiàn)程接收Client信息
Thread receivedThread = new Thread(ReceiveMessage);
receivedThread.Start(clientSocket);
}
}
private static void ReceiveMessage(object clientSocket)
{
Socket myClientSocket = (Socket) clientSocket;
while (true)
{
try
{
int revceiveNumber = myClientSocket.Receive(result);
//Console.WriteLine("接受客戶(hù)端{(lán)0}消息{1}", myClientSocket.RemoteEndPoint.ToString()
// , Encoding.ASCII.GetString(result, 0, revceiveNumber));
Console.WriteLine(Encoding.ASCII.GetString(result, 0, revceiveNumber));
if (myClientSocket == clientSocketA)
{
Console.WriteLine("receive from A");
if (clientSocketB!=null&&clientSocketB.IsBound)
{
Console.WriteLine("a IS BOUND");
clientSocketB.Send(result, 0, revceiveNumber, SocketFlags.None);
}
else
{
myClientSocket.Send(Encoding.ASCII.GetBytes("the people is not online! Send Failed!"));
Console.WriteLine("對(duì)方不在線(xiàn)上,發(fā)送失??!");
}
}
else
{
Console.WriteLine("receive from B");
if (clientSocketA != null && clientSocketA.IsBound)
{
Console.WriteLine("a IS BOUND");
clientSocketA.Send(result, 0, revceiveNumber, SocketFlags.None);
}
else
{
myClientSocket.Send(Encoding.ASCII.GetBytes("the people is not online! Send Failed!"));
Console.WriteLine("對(duì)方不在線(xiàn)上,發(fā)送失敗!");
}
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
myClientSocket.Shutdown(SocketShutdown.Both);
myClientSocket.Close();
break;
}
}
}
}
}
Client端代碼(因?yàn)槎疾畈欢?就只貼一個(gè)了)
namespace SocketClient
{
class Program
{
private static byte[] result = new byte[1024];
private static Socket clientSocket;
private static void ListenServer()
{
while (true)
{
result = new byte[1024];
int receiveLength = clientSocket.Receive(result);
Console.WriteLine("{0}", Encoding.ASCII.GetString(result, 0, receiveLength));
}
}
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clientSocket.Connect(ip, 8885);
Console.WriteLine("連接成功!");
}
catch (Exception e)
{
Console.WriteLine("連接失??!");
return;
}
Thread threadRead = new Thread(ListenServer);
threadRead.Start();
while(true)
{
try
{
Thread.Sleep(1000);
string sendMessage = Console.ReadLine();
clientSocket.Send(Encoding.ASCII.GetBytes("Sylvia:"+sendMessage));
}
catch (Exception ex)
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
break;
}
}
Console.WriteLine("發(fā)送完畢 按回車(chē)退出");
Console.ReadKey();
}
}
}
寫(xiě)的時(shí)候要特別注意一下Send信息的時(shí)候,注意byte[]的傳輸大小,很容易變成byte[]數(shù)組的大小而不是內(nèi)容的大小。
這個(gè)大家就自己嘗試吧。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
利用ASP.NET MVC和Bootstrap快速搭建響應(yīng)式個(gè)人博客站(一)
這篇文章主要介紹了利用ASP.NET MVC和Bootstrap快速搭建響應(yīng)式個(gè)人博客站(一)的相關(guān)資料,需要的朋友可以參考下2016-06-06
.Net使用RabbitMQ即時(shí)發(fā)消息Demo
RabbitMQ是一個(gè)在AMQP基礎(chǔ)上完整的,可復(fù)用的企業(yè)消息系統(tǒng),下面這篇文章主要給大家介紹了關(guān)于.Net使用RabbitMQ即時(shí)發(fā)消息的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-07-07
.Net WebApi消息攔截器之MessageHandler的示例
這篇文章主要介紹了.Net WebApi消息攔截器之MessageHandler的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
Linq to XML 用一句話(huà)讀出RSS文章列表代碼
Linq to XML 用一句話(huà)讀出RSS文章列表代碼2010-06-06
asp.net使用jquery實(shí)現(xiàn)搜索框默認(rèn)提示功能
這篇文章主要介紹了asp.net使用jquery實(shí)現(xiàn)搜索框默認(rèn)提示功能,大家參考使用吧2014-01-01
xls表格導(dǎo)入數(shù)據(jù)庫(kù)功能實(shí)例代碼
這篇文章介紹了xls表格導(dǎo)入數(shù)據(jù)庫(kù)功能實(shí)例代碼,有需要的朋友可以參考一下2013-10-10
asp.net 在處理向該請(qǐng)求提供服務(wù)所需的配置文件時(shí)出錯(cuò)
遭遇:“說(shuō)明: 在處理向該請(qǐng)求提供服務(wù)所需的配置文件時(shí)出錯(cuò)。請(qǐng)檢查下面的特定錯(cuò)誤詳細(xì)信息并適當(dāng)?shù)匦薷呐渲梦募?。”錯(cuò)誤2010-03-03

