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; } } } } }
先启动服务器端,在启动客户端,效果以下