源代码:
https://gitee.com/NKG_admin/SocketTestDemo
Socket 基础知识
既然谈到Socket,就得牵扯到服务器端,什么是服务器端呢?
个人理解:服务器端就是自己的代码,让它跑在云主机(云服务器上,比如阿里云,亚马逊云这些)。而这些,其实就是在云端买了一个主机,它和你正在使用的电脑一样,有桌面,有系统,有蜘蛛纸牌。。。
不同的是,它有固定的公网IP,而我们电脑公网IP是变化的(所以如果要把自己电脑变成服务器的话需要用花生壳做内网穿透)。
所以我们要把代码里绑定IP和连接IP的地方改成服务器的公网IP就行了。然后只需要把你服务器代码生成的exe文件在上面打开。让它365天没日没夜开着机就行了。
那么Socket到底是个啥?
先看一张图
**Socket是一个接口,是应用层与TCP/IP协议族通信的中间软件抽象层,在用户进程与TCP/IP协议之间充当中间人,完成TCP/IP协议的书写,用户只需理解接口即可。 **
在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。它的出现只是使得程序员更方便地使用TCP/IP协议栈而已。Socket本身并不是协议,它是应用层与TCP/IP协议族通信的中间软件抽象层,是一组调用接口(TCP/IP网络的API函数)。
TCP/IP协议又是个啥?
从上图可以看出可以看出TCP/IP协议族包括运输层、网络层、链路层。TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。就像操作系统会提供标准的编程接口,比如Win32编程接口一样,TCP/IP也必须对外提供编程接口,这就是Socket编程接口
Socket跟TCP/IP并没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以,Socket的出现只是可以更方便的使用TCP/IP协议栈而已,其对TCP/IP进行了抽象,形成了几个最基本的函数接口。比如create,listen,accept,connect,read和write等等。
socket只是对TCP/IP协议栈操作的抽象,而不是简单的映射关系,这很重要!
通俗点讲:
可以这样理解,你可以简单的理解为电话号码。你这边一个电话号码 发送信息,另一个电话号码接收你发送的消息。而中间传输这些信息的过程和技术就是TCP/IP,我们不需要了解,我们只需要知道要拨打的号码(Socket ip地址和端口)即可。你用的这个号码指定发给哪个号码,就只有哪个号码可以接收你发送的消息。这两个电话可收信息,可发信息。就是担任着Socket的角色。两个手机就是你用的电脑了。Socket也一样,指定了ip和端口就变成独一无二的电话号码了。
Message协议与解析代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ClientTest { class Message { private byte[] data = new byte[1024]; private int startIndex = 0; public void AddCount(int count) { startIndex += count; } public byte[] Data { get { return data; } } public int StartIndex { get { return startIndex; } } public int RemindSize { get { return data.Length - startIndex; } } public void ReadMessage() { while (true) { if (startIndex <= 4) { return; } int count = BitConverter.ToInt32(data, 0); if ((startIndex - 4) >= count) { string s = Encoding.UTF8.GetString(data, 4, count); Console.WriteLine("解析出来一条数据:" + s); Array.Copy(data, count + 4, data, 0, startIndex - 4 - count); startIndex -= (count + 4); } else { break; } } } public static byte[] GetBytes(string data) { byte[] dataBytes = Encoding.UTF8.GetBytes(data); int dataLength = dataBytes.Length; byte[] lengthBytes = BitConverter.GetBytes(dataLength); byte[] Bytes = lengthBytes.Concat(dataBytes).ToArray(); return Bytes; } } }
|
服务端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| using System; using System.Net; using System.Net.Sockets; using System.Text; namespace Server { class Program { static Message rec_Message = new Message(); static Socket serverSocket; static void Main(string[] args) { StartServer(); Console.ReadKey(); } static void StartServer() { serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ipAdress = IPAddress.Parse("127.0.0.1"); IPEndPoint iPEndPoint = new IPEndPoint(ipAdress, 88); serverSocket.Bind(iPEndPoint); serverSocket.Listen(0); serverSocket.BeginAccept(AcceptCallBack, serverSocket); } static void BeginSendMessagesToClient(Socket toClientsocket,string msg) { toClientsocket.Send(Message.GetBytes(msg)); } static void BeginReceiveMessages(Socket toClientsocket) { toClientsocket.BeginReceive(rec_Message.Data, rec_Message.StartIndex, rec_Message.RemindSize, SocketFlags.None, ReceiveCallBack, toClientsocket); } static void AcceptCallBack(IAsyncResult ar) { Socket toClientsocket = serverSocket.EndAccept(ar); Console.WriteLine("客户端{0}连接进来了。",toClientsocket.RemoteEndPoint.ToString()); string msg = "Hello client!你好。"; BeginSendMessagesToClient(toClientsocket, msg); BeginReceiveMessages(toClientsocket); serverSocket.BeginAccept(AcceptCallBack, serverSocket); } static void ReceiveCallBack(IAsyncResult ar) { Socket toClientsocket = null; try { toClientsocket = ar.AsyncState as Socket; int count = toClientsocket.EndReceive(ar); if (count == 0) { toClientsocket.Close(); return; } Console.WriteLine("从客户端:{0} 接收到数据,解析中。。。",toClientsocket.RemoteEndPoint); rec_Message.AddCount(count); rec_Message.ReadMessage(); BeginSendMessagesToClient(toClientsocket, "客户端"+toClientsocket.RemoteEndPoint+"我收到了你消息。"); toClientsocket.BeginReceive(rec_Message.Data, rec_Message.StartIndex, rec_Message.RemindSize, SocketFlags.None, ReceiveCallBack, toClientsocket); } catch (Exception e) { Console.WriteLine(e); if (toClientsocket != null) { toClientsocket.Close(); } } finally { } } } }
|
客户端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| using System; using System.Text; using System.Net.Sockets; using System.Net; namespace ClientTest { class Program { static Message rec_Message = new Message(); static Socket clientSocket; static void Main(string[] args) { StartClient(); while (true) { Console.WriteLine("请输入想要向服务器发送的字符串:"); string data = Console.ReadLine(); BeginSendMessagesToServer(data); } } static void StartClient() { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { clientSocket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 88)); Console.WriteLine("连接服务器成功"); } catch (Exception e) { Console.WriteLine(e); Console.WriteLine("连接服务器失败"); } BeginSendMessagesToServer("Hello,服务器端。"); BeginReceiveMessages(); } static void BeginSendMessagesToServer(string msg) { try { clientSocket.Send(Message.GetBytes(msg)); Console.WriteLine("{0} 发送成功!",msg); } catch(Exception e) { Console.WriteLine(e); } } static void BeginReceiveMessages() { clientSocket.BeginReceive(rec_Message.Data, rec_Message.StartIndex, rec_Message.RemindSize, SocketFlags.None, ReceiveCallBack, null); } static void ReceiveCallBack(IAsyncResult ar) { try { int count = clientSocket.EndReceive(ar); Console.WriteLine("从客户端接收到数据,解析中。。。"); rec_Message.AddCount(count); rec_Message.ReadMessage(); clientSocket.BeginReceive(rec_Message.Data, rec_Message.StartIndex, rec_Message.RemindSize, SocketFlags.None, ReceiveCallBack, null); } catch (Exception e) { Console.WriteLine(e); } } } }
|