一、socket简介
socket就是套接字,它是引用网络连接的特殊文件描述符,由三个基本要素组成:
1: AddressFamily(网络类型)
2: SocketType(数据传输类型)
3:ProtocolType(采用的网络协议)
下面是可用于IP通信的套接字组合及其常用的属性和方法
二、socket与网络通信
IP连接领域有两种通信类型:面向连接的和无连接的,这里我要讲的是面向连接的,使用TCP协议来建立两个IP的值端点之间的会话,下面是它的基本步骤。
a:建立一个套接字
b:绑定本机的IP和端口
c:使用listen()方法监听别人发过来的东西
d:如果监听到连接,则可以使用Send/Receive来执行操作
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; } } } } }
先启动服务器端,在启动客户端,效果如下