本例內容為書上1.4.4內容的改版,主要實現服務端和客戶端分離。
使用socket:
服務端程序:
int dataLength; string tmpStr; byte[] dataBytes1 = new byte[1024]; //指定監聽端口開始 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint myHost = new IPEndPoint(IPAddress.Any, 8080); //指定監聽端口結束 EndPoint client1 = new IPEndPoint(IPAddress.Any, 8080); socket.Bind(myHost); do { Console.WriteLine("等待接收..."); dataLength = socket.ReceiveFrom(dataBytes1, ref client1); tmpStr = System.Text.Encoding.Unicode.GetString(dataBytes1, 0, dataLength); Console.WriteLine($"接收到來自{client1.ToString()}的信息:{tmpStr}"); }while (tmpStr.ToLower() != "serverover"); socket.Close(); Console.WriteLine("對方已要求服務器退出,請按回車鍵結束。"); Console.ReadLine();
客戶端程序:
byte[] dataBytes; string tmpStr; Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //指定使用哪個套接字發送開始 IPEndPoint myHost = new IPEndPoint(IPAddress.Any, 8081); socket.Bind(myHost); //指定使用哪個套接字發送結束 //指定服務器開始 IPEndPoint remoteIPEnd = new IPEndPoint(IPAddress.Parse("192.168.1.105"), 8080); //指定服務器結束 do { Console.Write("輸入發送信息(exit退出):"); tmpStr = Console.ReadLine(); dataBytes = System.Text.Encoding.Unicode.GetBytes(tmpStr); socket.SendTo(dataBytes, remoteIPEnd); } while (tmpStr.ToLower() != "exit"); socket.Close(); Console.WriteLine("已經退出,請按回車鍵結束。"); Console.ReadLine();
運行效果:
不同電腦測試也通過。
基於此,就應當能很輕松完成P24頁第4題了。
使用udpclient:
服務端:
static UdpClient udp; static void Main(string[] args) { string msg; IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9000),remote=new IPEndPoint(IPAddress.Any,0); udp = new UdpClient(ipep); do { msg = Encoding.UTF8.GetString(udp.Receive(ref remote)); Console.WriteLine($"{remote.ToString()}:{msg}"); } while (msg.ToLower() != "exit"); }
客戶端:
static UdpClient udp; static void Main(string[] args) { IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9100); udp = new UdpClient(ipep); udp.Connect(IPAddress.Parse("127.0.0.1"), 9000); string msg; byte[] b; do { msg = Console.ReadLine(); b = Encoding.UTF8.GetBytes(msg); udp.Send(b, b.Length); } while (msg.ToLower() != "exit"); }
擴展:
都寫到這里了,大家結合之前的網絡知識,再思考一下,如何突破單邊的源地址轉換限制,實現內網和公網pc收發消息?
提示:內網機器先發出消息,利用出口轉換表里的地址和端口對應關系,讓服務器也可以訪問到客戶機。
代碼修改1:發送消息程序,服務器ip和端口需要在運行時由用戶指定。
代碼修改2:內網機器的發送和接收,使用了相同的ip和端口。必須開啟端口復用才能工作。代碼為:“socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);”
效果如下圖:
其中,遠程桌面使用的是一台公網機器,右側是本機。
運行順序為圖中順序。
此時,內網機器也能夠被其他內網機器連接並接收消息:
這也是qq最基本的通信原理。
思考題:如何利用一台公網服務器,構建簡單聊天程序?