简易的自定义Web服务器

基于浏览器向服务端发起请求

两台主机各自的进程之间相互通信,需要协议、IP地址和端口号,IP表示了主机的网络地址,而端口号则表示了主机上的某个进程的地址,IP加Port统称为端点(EndPoint),在网络编程的世界里,.NET提供了Socket(套接字)类,此类处于传输层之中,Socket使开发人员可以以编程的方式侦听远程主机向本机发送的数据,并对到达传输层的数据包做出处理,同时它还可以向远程发送数据包。也即,Socket用于处理传输的数据。

 );
             );];, , len );,  };

clientSocket.Send( HttpDataLineByte );
                clientSocket.Send( HttpHeaderByte );
                clientSocket.Send( HttpNullLineByte );
                clientSocket.Send( HttpBodyByte );

//断开连接
                clientSocket.Close( );              
            }
        }
    }
}

在浏览器输入端点进行访问,因为浏览器实已经实现了Http协议,浏览器处于应用层,封装好请求后会往下传递给传输层,封装TCP端口再传递给网络层直到请求发送至服务端,所以可以直接看到服务端返回的结果:

TcpListener封装了Socket,所以也可以使用TcpListener来监听请求

  , HttpBodyByte.Length );
                }
                //断开连接
                clientTcp.Close( );              
            }
        }
    }
}

基于windows窗体实现双方发送即时通信

分别创建两个windows窗体项目,命名为TCPServer和TCPClient。两个项目的窗体控件的名称是一样的,如下:

服务端通过TcpListener开启监听,然后通过开启新的线程并使用TcpListener的AcceptTcpClient方法去监听客户端的请求,而客户端则开启新线程并通过TcpClient发起远程连接请求。这样双方就可以建立一个连接。接着,服务端的AcceptTcpClient方法会阻塞线程直到接受到一个请求为止,此时它会返回一个NetworkStream实例,此类提供了读取远程数据、发送数据的方法,此后,双方的互动都是通过这个唯一的NetworkStream实例的方法(Read、Write)来完成,发送数据和接收数据时都使用新线程来处理,并且应将发送数据和接收数据的逻辑都放入try块,这样一旦互动过程出现异常则可以关闭当前的Tcp连接、清空NetworkStream资源,然后服务端重新开启新线程继续监听客户端的连接请求,而客户端则重新发送远程连接的请求即可。

服务端源码

 
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
;
         );
            
             ); //模拟发送延时
                    writer.Flush( );
                    statusStrip.Invoke( showStatusMessage, "消息发送成功……" );
                    ShowMessageBox.Invoke( showGetOrSendMessage, senMsg );//在创建"公共消息框控件"的线程上调用showGetOrSendMessage委托来显示消息
                }
                catch 
                {
                    //如果出现异常则需要关闭现有连接,清除所有资源后重新开始
                    statusStrip.Invoke( showStatusMessage, "消息发送失败……" );
                    if (client != null) client.Close( );
                    if (reader != null) reader.Close( );
                    if (writer != null) writer.Close( );
                    //重新开启新线程来接收请求
                    Thread thread = new Thread( Request );
                    thread.Start( );
                }
            } );

proxyThread.Start( );
        }

//关闭监听
        private void CloseTcpListen_Click( object sender, EventArgs e )
        {
            if (client != null) client.Close( );
            if (reader != null) reader.Close( );
            if (writer != null) writer.Close( );
            lister.Stop( );
            statusStrip.Invoke( showStatusMessage, "监听已经关闭……" );
        }

//断开连接
        private void NoConnect_Click( object sender, EventArgs e )
        {
            if (client != null) client.Close( );
            if (reader != null) reader.Close( );
            if (writer != null) writer.Close( );
            statusStrip.Invoke( showStatusMessage, "连接已断开……" );
        }

//清空消息
        private void ClearMessage_Click( object sender, EventArgs e )
        {
            ShowMessageBox.Clear( );
        }

//点击关闭窗口按钮时,关闭TCP侦听,否则它会一直开启
        private void Server_FormClosing( object sender, FormClosingEventArgs e )
        {
            lister.Stop( );
        }
    }
}

客户端源码

 );  );
                    ShowMessageBox.Invoke( showGetOrSendMessage, sendMsg );
                    statusStrip.Invoke( showStatusMessage, "消息发送成功……" );
                }
                catch
                {
                    //如果出现异常则关闭现有连接,清除所有资源
                    statusStrip.Invoke( showStatusMessage, "消息发送失败……" );
                    if (server != null) server.Close( );
                    if (reader != null) reader.Close( );
                    if (writer != null) writer.Close( );
                    statusStrip.Invoke( showStatusMessage, "连接已经断开,请重新点击'连接服务器'按钮……" );
                }
            } );
            proxyThread.Start( );
        }

//断开连接
        private void NoConnect_Click( object sender, EventArgs e )
        {
            if (server != null) server.Close( );
            if (reader != null) reader.Close( );
            if (writer != null) writer.Close( );
            statusStrip.Invoke( showStatusMessage, "连接已断开……" );
        }

//清空消息
        private void ClearMessage_Click( object sender, EventArgs e )
        {
            ShowMessageBox.Clear( );
        }

//关闭窗口
        private void CloseWin_Click( object sender, EventArgs e )
        {
            this.Close( );
        }
    }
}

参考资料

msdn:基于TCP协议的简单通信程序

网络知识 - 学习总目录

网络知识 - 简易的自定义Web服务器的更多相关文章

  1. C# 编写简易 ASP.NET Web 服务器

    C# 编写简易 ASP.NET Web 服务器 你是否有过这样的需求——想运行 ASP.NET 程序,又不想安装 IIS 或者 Visual Studio?我想如果你经常编写 ASP.NET 程序的话 ...

  2. atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty  HttpListener

    atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty  HttpListener 1. 自定义web服务器的实现方案,基于原始socket vs   ...

  3. 自定义web服务器(四)

    关于HTTP协议的具体内容,前面章节已经有所讲解,相信读者已有所了解,在此不在累述,本章节讲解自定义web服务器.  一,.net提供自定义Web服务器的类 以下只是写主要的类 1.HTTPListe ...

  4. [C# 网络编程系列]专题三:自定义Web服务器

    转自:http://www.cnblogs.com/zhili/archive/2012/08/23/2652460.html 前言: 经过前面的专题中对网络层协议和HTTP协议的简单介绍相信大家对网 ...

  5. 使用 C# 编写简易 ASP.NET Web 服务器

    原文 http://www.cnblogs.com/lcomplete/p/use-csharp-write-aspnet-web-server.html 如果你想获得更好的阅读体验,可以前往我在 g ...

  6. 转:【专题三】自定义Web服务器

    前言: 经过前面的专题中对网络层协议和HTTP协议的简单介绍相信大家对网络中的协议有了大致的了解的, 本专题将针对HTTP协议定义一个Web服务器,我们平常浏览网页通过在浏览器中输入一个网址就可以看到 ...

  7. 使用 C# 编写简易 ASP.NET Web 服务器 ---- 模拟IIS的处理过程

    如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/07/16/use-csharp-write-asp ...

  8. Servlet学习笔记【1】--- 背景和基础知识(CGI、Web服务器发展史、Servlet简介、任务、继承结构)

    本文主要讲Servlet的基础知识和背景知识. 1 CGI简介 CGI(Common Gateway Interface 公共网关接口)是WWW技术中最重要的技术之一,有着不可替代的重要地位.CGI是 ...

  9. 专题三:自定义Web服务器

    前言: 经过前面的专题中对网络层协议和HTTP协议的简单介绍相信大家对网络中的协议有了大致的了解的, 本专题将针对HTTP协议定义一个Web服务器,我们平常浏览网页通过在浏览器中输入一个网址就可以看到 ...

随机推荐

  1. spring boot拦截器WebMvcConfigurerAdapter,以及高版本的替换方案(转)

    文章转自 http://blog.51cto.com/12066352/2093750 最近项目采用spring icloud,用的spring boot版本是1.5.x的,spring boot 2 ...

  2. STM32407+LAN8720A+LWIP 实现TCP Client

    硬件 一.配置CubeMax工程 二.配置系统时钟 因为LAN8720使用的是外部25MHz的晶振,所以不需要单片机输出时钟 三.配置ETH和LWIP参数 四.更改代码 LAN8720A在初始化的时候 ...

  3. Command "python setup.py egg_info" failed with error code 1 in c:\users\w5659\appdata\local\temp\pip-build-fs2yzl\ipython\

    Error Msg: Collecting ipython Using cached https://files.pythonhosted.org/packages/5b/e3/4b3082bd7f6 ...

  4. 基于Flask 实现Web微信登陆

    网页版微信登陆网址 https://login.wx.qq.com/ 获取微信登陆的二维码 在浏览器中访问登陆接口 https://login.wx.qq.com/ 我们查找二维码的图片可以看到 其中 ...

  5. Ajax 简单的实例代码

    <!DOCTYPE HTML><html><head><script src="http://libs.baidu.com/jquery/2.0.0 ...

  6. [BZOJ 3992] [SDOI 2015] 序列统计

    Description 传送门 Solution [一] 设 \(f[i][j]\) 表示前 \(i\) 个数的乘积在模 \(p\) 意义下等于 \(j\) 的方案数,有 \[ f[i][j]=\su ...

  7. P1033 自由落体

    原题链接 https://www.luogu.org/problemnew/show/P1033 不得不说,这个题太坑了!!!主要是题目说得不明确...... 先来看图: 看一下用红圈圈起来的部分,就 ...

  8. 【XSY2843】「地底蔷薇」 NTT什么的 扩展拉格朗日反演

    题目大意 给定集合\(S\),请你求出\(n\)个点的"所有极大点双连通分量的大小都在\(S\)内"的不同简单无向连通图的个数对\(998244353\)取模的结果. \(n\le ...

  9. Input标签使用整理

    0 写在前面 对于程序而言I/O是一个程序的重要组成部分.程序的输入.输出接口,指定了程序与用户之间的交互方式.对于前端开发而言,input标签也有着其重要地位,它为用户向服务端提交数据提供了可能. ...

  10. [拓展Bsgs] Clever - Y

    题目链接 Clever - Y 题意 有同余方程 \(X^Y \equiv K\ (mod\ Z)\),给定\(X\),\(Z\),\(K\),求\(Y\). 解法 如题,是拓展 \(Bsgs\) 板 ...