socket就是套接字,它是引用網絡鏈接的特殊文件描述符,由三個基本要素組成:服務器
1: AddressFamily(網絡類型)網絡
2: SocketType(數據傳輸類型)socket
3:ProtocolType(採用的網絡協議)ide
下面是可用於IP通訊的套接字組合及其經常使用的屬性和方法函數
IP鏈接領域有兩種通訊類型:面向鏈接的和無鏈接的,這裏我要講的是面向鏈接的,使用TCP協議來創建兩個IP的值端點之間的會話,下面是它的基本步驟。spa
a:創建一個套接字線程
b:綁定本機的IP和端口code
c:使用listen()方法監聽別人發過來的東西blog
d:若是監聽到鏈接,則能夠使用Send/Receive來執行操做dns
e:完成後使用Close()方法進行關閉
工做原理如圖所示:
下面的例子中,服務器向全部鏈接的客戶端發送消息,實現多播功能
using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace ServerFinally { class Program { //定義兩個鏈表,分別存儲鏈接的客戶端和斷開的客戶端信息類 //並非一個socket,而是本身寫的一個輔助類 public static List<ClientCon> connectSockets = new List<ClientCon>(); public static List<ClientCon> disConnectSockets = new List<ClientCon>(); static void Main(string[] args) { //經過dns類獲取本機ip地址(也能夠直接輸入IP地址) IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); IPAddress ipaddress = ipHostInfo.AddressList[2]; IPEndPoint ipe = new IPEndPoint(ipaddress, 9999); Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { listener.Bind(ipe); listener.Listen(10); //死循環 一直等待客戶端鏈接 while (true) { Console.WriteLine("Wait for a connnect..."); Socket client = listener.Accept(); //阻塞當前線程 Console.WriteLine("A client is connct..."); //每次鏈接一個客戶端,將其加入鏈表 ClientCon clientCon = new ClientCon(client); connectSockets.Add(clientCon); //開啓線程調用接受消息方法,一直接受消息 Thread t = new Thread(clientCon.ReceiveMessage); t.Start(); Console.WriteLine("Start receive"); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } //廣播消息,將信息發送至全部已鏈接的客戶端 public static void BroadcastMessage(string data) { foreach (ClientCon client in connectSockets) { //判斷鏈表中的客戶端是否已經斷開,未斷開鏈接就向其發送消息,不然從中移除 if (client.IsConnected) { client.SendMessage(data); } else { disConnectSockets.Add(client); } } foreach (ClientCon disConnect in disConnectSockets) { connectSockets.Remove(disConnect); } } } }
using System; using System.Collections.Generic; using System.Net.Sockets; using System.Text; namespace ServerFinally { /// <summary> /// 客戶端鏈接輔助類 /// </summary> class ClientCon { Socket client; //判斷當前客戶端是否斷開鏈接 public bool IsConnected { get; set; } //構造函數 調用的時候爲cliet賦值 public ClientCon(Socket s) { client = s; IsConnected = true; } //接受客戶端發送的信息 public void ReceiveMessage() { byte[] buffer = new byte[1024]; string data = ""; while (true) { try { //判斷客戶端是否斷開鏈接 if (!client.Poll(10, SelectMode.SelectRead)) { int length = client.Receive(buffer); data = Encoding.UTF8.GetString(buffer, 0, length); if (data != "") { Console.WriteLine("Receive message is :" + data); Program.BroadcastMessage(data); } } else { IsConnected = false; Console.WriteLine("A client is disconnect"); break; } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } //發送消息 public void SendMessage(string data) { byte[] buffer = new byte[1024]; buffer = Encoding.UTF8.GetBytes(data); client.Send(buffer); } } }
using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace ClientFinally { class Program { static Socket client; static Thread t; static void Main(string[] args) { //經過IP地址和端口定義一個IPEndPoint類 IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("10.128.119.68"), 9999); client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { //鏈接服務器 client.Connect(ipe); Console.WriteLine("Connnect to {0}", client.RemoteEndPoint.ToString()); //開啓線程 接收消息 t = new Thread(ReceiveMessage); t.Start(); //經過死循環發送消息 while (true) { byte[] bytes = new byte[1024]; Console.WriteLine("Please input you message:"); string mes = Console.ReadLine(); //若是輸入的內容爲空 關閉此客戶端 if (mes == "") { client.Shutdown(SocketShutdown.Both); client.Close(); break; } bytes = Encoding.UTF8.GetBytes(mes); //發送消息 client.Send(bytes); } } catch (Exception e) { Console.WriteLine(e.Message); } } //接收消息 private static void ReceiveMessage() { while (true) { try { byte[] buffer = new byte[1024]; //length爲接收信息長度 int length = client.Receive(buffer); if (length > 0) { Console.WriteLine("receive message:" + Encoding.UTF8.GetString(buffer)); } } catch { break; } } } } }
先啓動服務器端,在啓動客戶端,效果以下