基於c#用Socket做一個局域網聊天工具。本站提示廣大學習愛好者:(基於c#用Socket做一個局域網聊天工具)文章只能為提供參考,不一定能成為您想要的結果。以下是基於c#用Socket做一個局域網聊天工具正文
順序設計成為復雜的服務端和客戶端之間的通訊, 但經過一些辦法可以將這兩者停止一致起來, 讓服務端也成為客戶端, 讓客戶端也成為服務端, 使它們之間可以相互隨時不連續的通訊. 思索到完成最原始的服務端和客戶端之間的通訊所需求的步驟關於寫這樣的順序是很有協助的.
作為服務端, 要聲明一個Socket A並綁定(Bind)某一個IP+這個IP指定的通訊端口, 比方這個是127.0.0.1:9050, 然後開端監聽(Listen), Listen可以監聽來自多個IP傳過去的銜接懇求, 詳細可以同時銜接幾個客戶端, Listen辦法中可以設定一個參數. 假如Listen到某一個客戶端發來銜接懇求了, 這時定義一個新的Socket B專門擔任與這個客戶端的通訊, Socket B = A.Accept(). 這時可以獲取這個客戶端的IP和端口, IPEndPoint C = (IPEndPoint)B.RemoteEndPoint, C.Address和C.Port辨別表示客戶端C的IP地址和端口. 這時經過B.Send()辦法就可以給C發送音訊了, B.Receive()可以接納客戶端C發來的信息.
作為客戶端, 也需求聲明一個Socket D並綁定某一個IP+本機一個未被占用的端口, 定義IPEndPoint E表示要停止銜接的服務端Socket, 要指明E的IP和端口, 這樣才可以停止端口對端口之間的通訊, 接上去就可以嘗試D.Connect(E), 銜接成功之後就可以發送和接納數據了, D.Send(), D.Receive.
發送音訊時, 數據都是以字節或字節數組為單位停止傳輸的, 比方我客戶端D要發送"Hello World"則要這樣寫: D.Send(Encoding.ASCII.GetBytes("Hello World")). 承受音訊時, 也是以字節或字節數組, 比方服務端要承受D方才發送的Hello World, 可以這樣寫: Byte[] data = new Byte[1024]; int receivedDataLength = B.Receive(data); string stringdata = Encoding.ASCII.GetString(data, 0, receivedDataLength); stringdata這時就是Hello World.
下面只是大約的論述了服務端與客戶端之間的通訊進程, 在網上找到了詳細的代碼例子, 也貼過去參考參考. 這個例子沒有將服務端與客戶端一致起來, 他是辨別寫服務端和客戶端的.
服務端代碼
using System; using System; using System.Net; using System.Net.Sockets; using System.Text; namespace tcpserver { /// <summary> /// Class1 的摘要闡明。 /// </summary> class server { /// <summary> /// 使用順序的主入口點。 /// </summary> [STAThread] static void Main( string [] args) { // // TODO: 在此處添加代碼以啟動使用順序 // int recv; // 用於表示客戶端發送的信息長度 byte [] data;// = new byte [ 1024 ]; // 用於緩存客戶端所發送的信息,經過socket傳遞的信息必需為字節數組 IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050 ); // 本機預運用的IP和端口 Socket newsock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); newsock.Bind(ipep); // 綁定 newsock.Listen( 10 ); // 監聽 Console.WriteLine( " waiting for a client " ); Socket client = newsock.Accept(); //當有可用的客戶端銜接嘗試時執行,並前往一個新的socket,用於與客戶端之間的通訊 IPEndPoint clientip = (IPEndPoint)client.RemoteEndPoint; Console.WriteLine( " connect with client: " + clientip.Address + " at port: " + clientip.Port); string welcome = " welcome here! " ; data = Encoding.ASCII.GetBytes(welcome); client.Send(data,data.Length,SocketFlags.None); // 發送信息 while ( true ) { // 用死循環來不時的從客戶端獲取信息 data = new byte [ 1024 ]; recv = client.Receive(data); Console.WriteLine( " recv= " + recv); if (recv == 0 ) // 當信息長度為0,闡明客戶端銜接斷開 break ; Console.WriteLine(Encoding.ASCII.GetString(data, 0 ,recv)); client.Send(data,recv,SocketFlags.None); } Console.WriteLine( " Disconnected from " + clientip.Address); client.Close(); newsock.Close(); } } }
客戶端代碼
using System; using System.Net; using System.Net.Sockets; using System.Text; namespace tcpclient { /// <summary> /// Class1 的摘要闡明。 /// </summary> class client { /// <summary> /// 使用順序的主入口點。 /// </summary> [STAThread] static void Main(string[] args) { // // TODO: 在此處添加代碼以啟動使用順序 // byte[] data = new byte[1024]; Socket newclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); newclient.Bind(new IPEndPoint(IPAddress.Any, 905)); Console.Write(" please input the server ip: "); string ipadd = Console.ReadLine(); Console.WriteLine(); Console.Write(" please input the server port: "); int port = Convert.ToInt32(Console.ReadLine()); IPEndPoint ie = new IPEndPoint(IPAddress.Parse(ipadd), port); // 服務器的IP和端口 try { // 由於客戶端只是用來向特定的服務器發送信息,所以不需求綁定本機的IP和端口。不需求監聽。 newclient.Connect(ie); } catch (SocketException e) { Console.WriteLine(" unable to connect to server "); Console.WriteLine(e.ToString()); return; } int receivedDataLength = newclient.Receive(data); string stringdata = Encoding.ASCII.GetString(data, 0, receivedDataLength); Console.WriteLine(stringdata); while (true) { string input = Console.ReadLine(); if (input == " exit ") break; newclient.Send(Encoding.ASCII.GetBytes(input)); data = new byte[1024]; receivedDataLength = newclient.Receive(data); stringdata = Encoding.ASCII.GetString(data, 0, receivedDataLength); Console.WriteLine(stringdata); } Console.WriteLine(" disconnect from sercer "); newclient.Shutdown(SocketShutdown.Both); newclient.Close(); } } }
下面的服務端和客戶端都是控制台使用順序, 想方法做一個窗體類型的, 思緒就是另起一個線程, 這個線程專門擔任兩端樹立銜接. 假如不采用另起線程的辦法, 當等候銜接而沒有銜接上, 或許自動銜接, 服務端還沒有相應時, 順序就會呈現沒有呼應的假死形態.
當這個線程將兩個端口銜接成功後, 就讓順序進入一個死循環, 這個死循環擔任不時的接納能否有音訊傳來, 傳來的話就在txtGetMsg中顯示出來:
while (true) // 用死循環來不時的獲取信息 { data = new byte[1024]; recv = newclient.Receive(data); uiContext.Send(new SendOrPostCallback( state => { int txtGetMsgLength = txtGetMsg.Text.Length; string recMsg = "Friend: " + System.DateTime.Now.ToString() + "\n " +Encoding.Unicode.GetString(data, 0, recv) + "\n"; txtGetMsg.AppendText(recMsg); txtGetMsg.Select(txtGetMsgLength, recMsg.Length - Encoding.Unicode.GetString(data, 0, recv).Length - 1); txtGetMsg.SelectionColor = Color.Red; }), null); }
假如按下發送音訊的按鈕, 則發送txtSendMsg中的文本, 我寫的是用Unicode編碼, 所以可以發送中文字符.
private void btnSendMsg_Click(object sender, EventArgs e) { string input = txtSendMsg.Text; if (input == "") { MessageBox.Show("音訊不能為空!", "發送音訊出錯"); txtSendMsg.Focus(); } else { if (meIsClient) { newclient.Send(Encoding.Unicode.GetBytes(input)); string showText = "Me: " + System.DateTime.Now.ToString() + "\n " + input + "\n"; int txtGetMsgLength = txtGetMsg.Text.Length; txtGetMsg.AppendText(showText); txtGetMsg.Select(txtGetMsgLength, showText.Length - 1 - input.Length); txtGetMsg.SelectionColor = Color.Blue; txtSendMsg.Text = ""; } else { client.Send(Encoding.Unicode.GetBytes(input)); string showText = "Me " + System.DateTime.Now.ToString() + "\n " + input + "\n"; int txtGetMsgLength = txtGetMsg.Text.Length; txtGetMsg.AppendText(showText); txtGetMsg.Select(txtGetMsgLength, showText.Length - 1 - input.Length); txtGetMsg.SelectionColor = Color.Blue; txtSendMsg.Text = ""; } } }
順序的運轉效果:
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支持。