续上篇《你也可以写个聊天程序 - C# Socket学习1》
前言这里说的服务器是Web服务器,是类似IIS、Tomcat之类的,用来响应浏览器请求的服务。
Socket模拟浏览器的Url Get请求首先浏览器的请求是HTTP协议。我们上一篇说过,HTTP是短连接,用完就断开,是无状态的。所以我们在等待响应的时候不需要另外开个线程循环等待。
也就是我们只需要通过Socket和服务器建立连接,然后发送请求,然后接收服务器的响应,这样就完成了一次请求。
可是,我们一般访问网页的时候都是通过域名,没有IP也没有端口,怎么和服务器建立连接了。这里就需要用到我们上篇介绍的几个类了:
对于HTTP没有显示端口默认都是80 (为了简单这里就先不考虑HTTPS了)
知道了IP和端口,连接是可以建立了,为了得到正确的响应,我们应该给服务器发送什么消息呢?这里就需要用到HTTP协议了。
具体协议这里就不说了,我们先F12看看浏览器的请求报文,然后依葫芦画瓢试试,以为例。(现在找个非HTTPS的地址也是不容易了)
然后我们代码实现如下: void ...() { //得到主机信息 IPHostEntry ipInfo = Dns.GetHostEntry(new Uri("").Host); //取得IPAddress[] IPAddress[] ipAddr = ipInfo.AddressList; //得到服务器ip IPAddress ip = ipAddr[0]; //组合远程终结点 IPEndPoint ipEndPoint = new IPEndPoint(ip, 80); //创建Socket 实例 Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //尝试连接 socketClient.Connect(ipEndPoint); //发送请求 Send(socketClient); //接收服务器的响应 Receive(socketClient); } //接收来自服务端的消息 void Receive(Socket socketClient) { byte[] data = new byte[1024 * 1024]; while (true) { //读取客户端发送过来的数据 int readLeng = socketClient.Receive(data, 0, data.Length, SocketFlags.None); textBox2.AppendText($"{socketClient.RemoteEndPoint}:{Encoding.UTF8.GetString(data, 0, readLeng)}\r\n"); } } //发送消息到服务端 void Send(Socket socketClient) { //为了方便演示,仅用请求报文的前两行即可。(切记:需要严格按照报文格式。如,最后需要连续两次换行) var msg = $"GET / HTTP/1.1\r\nHost: {new Uri(textBox1.Text).Host}\r\n\r\n"; socketClient.Send(Encoding.UTF8.GetBytes(msg)); }
整个流程也就是:
1、dns服务把域名解析成ip
2、通过ip和端口和服务器建立连接(三次握手)
3、获取html文档
4、根据文档里面的链接(js、css、img)再重复以上过程
【注意】:发送报文的时候需要严格按照报文格式。如,最后需要连续两次换行、行末不能有空格等。
效果图:
Web服务器的实现和我们上一篇的Socket聊天服务端其实也差不多。
不同之处就在于,解析请求报文,然后按HTTP协议回复标准的响应报文(我这里为了简单,就没有按标准的协议来玩,仅仅只是实现了表面的效果)
代码如下: