使用Socket编程创建简单服务器和客户端
要知道的
Socket—AddressFamily, SocketType, ProtocolType
https://blog.csdn.net/weixin_42464466/article/details/84782870
-
AddressFamily.Internet表示IPV4地址
-
AddressFamily.InternetV6表示IPV6地址
-
SocketType.Stream-数据流 对应TCP协议传输数据
-
SocketType.gram-数据报 对应UDP协议传输数据
-
ProtocolType.TCP
-
ProtocolType.UDP
EndPoint和IPEndPoint
-
节点,标明了IP地址和端口号,由于
套接字(Socket)
需要绑定在一个进程上面,通过节点(IP: port)来确定 -
对于TCP/IP协议而言,一台计算机有 0~66535个端口(有的已被占用,自定义申请时多使用靠后的端口号)
参考:https://blog.csdn.net/tianlansedeshijie/article/details/95357734
-
IPEndPoint继承于EndPoint。IPEndPoint引用的时候参数为IP和端口。IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
-
.net中 Bind(EndPoint localEP);方法参数是EndPoint,填入IPEndPoint会按照EndPoint参数执行。
EndPoint是IPEndPoint的基类,IPEndPoint可以强转为EndPoint。EndPoint ep = (EndPoint)iep;
-
主要原因是IPEndPoint可以自己写入IP地址和端口。
Socket三种监听方式
https://www.cnblogs.com/pctzhang/archive/2012/02/02/2335324.html
-
new Socket(...).Accept()
-
new Socket(...).AcceptAsync(SocketAsyncEventArgs e)
-
new Socket(...).BeginAccept()
Semaphore
#regin和#endregin
归并折叠其中的代码块
源码
功能
-
互相发送一条消息并接收
-
暂无用户自定义消息内容功能——
Console.ReadLine()
-
暂无多次通讯功能——线程中添加while循环或其他(异步接收方法等)
// 服务器端 using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace Demo01_SocketTest_Sever { class SeverEnd { private static Socket severSocket; static void Main(string[] args) { // 1. 建立服务器 severSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); // 2. 绑定进程 severSocket.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.105"),6666)); // 3. 规定同时连接客户端数量 severSocket.Listen(10); // 4. 提示服务器启动成功 Console.WriteLine("服务器启动成功"); // 5. 建立Accept等待连接线程(Accpet方法如果没有连接则会挂起,这里使用线程来处理) Thread severAcceptThread = new Thread(SeverAccept);// new Thread(委托) severAcceptThread.Start(); // 6. 暂停主线程 Console.ReadKey(); } // 线程委托方法——Accept private static void SeverAccept() { // 1. 建立客户端实例 Socket clientInstance = severSocket.Accept(); // 2. 向客户端发送消息肯定连接成功 clientInstance.Send(Encoding.Default.GetBytes("服务器发来消息:连接成功")); // 3. 建立Receive接收消息线程(Receive方法如果没有连接则会挂起,这里使用线程来处理) Thread severReceiveThread = new Thread(SeverReceive); severReceiveThread.Start(clientInstance); } // 线程委托方法——Receive private static void SeverReceive(Object clientSocket) { // 1. 构建byte数组(充当缓冲区用于存储客户端发来的消息) byte[] data = new byte[1024]; // 2. 接收客户端clientSocket发来的消息,并存储至data缓冲区,且返回数据字节长度 int length = (clientSocket as Socket).Receive(data); // 3. 打印输出接收到的消息(相当于处理数据) Console.WriteLine(Encoding.UTF8.GetString(data,0,length)); } } } // 客户端 using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace Demo01_SocketTest_Client { class Program { private static Socket clientSocket; static void Main(string[] args) { // 1. 创建客户端Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 2. 建立连接(请求,对应SeverEnd中第五步) clientSocket.Connect(new IPEndPoint(IPAddress.Parse("192.168.0.105"),6666)); // 3. 提示连接成功 Console.WriteLine("连接成功"); // 4. 向服务器发送消息 clientSocket.Send(Encoding.UTF8.GetBytes("来自客户端:你好呀服务器!")); // 5. 建立Receive接收消息线程(接收来自服务器端的消息),Receive方法如果没有连接则会挂起,这里使用线程来处理 Thread clientReceiveThread = new Thread(ClientReceive); // 6. 暂停主线程 Console.ReadKey(); } // 线程委托方法 private static void ClientReceive() { // 1. 构建byte数组(充当缓冲区用于存储服务器端发来的消息) byte[] data = new byte[1024]; // 2. 接收由服务器端发来的消息,并存储至data缓冲区,且返回消息字节长 int length = clientSocket.Receive(data); // 3. 打印输出接收到的消息(相当于处理数据) Console.WriteLine(Encoding.UTF8.GetString(data,0,length)); } } }