简易的自定义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. 实战申请Let's Encrypt永久免费SSL证书过程教程及常见问题

    最近需要https这里看到一份不错的博客,收录一下! Let's Encrypt作为一个公共且免费SSL的项目逐渐被广大用户传播和使用,是由Mozilla.Cisco.Akamai.IdenTrust ...

  2. 一文搞懂Raft算法

      raft是工程上使用较为广泛的强一致性.去中心化.高可用的分布式协议.在这里强调了是在工程上,因为在学术理论界,最耀眼的还是大名鼎鼎的Paxos.但Paxos是:少数真正理解的人觉得简单,尚未理解 ...

  3. Winform开发框架中工作流模块的动态处理

    在工作流处理表中,首先我们区分流程模板和流程实例两个部分,这个其实就是类似模板和具体文档的概念,我们一份模板可以创建很多个类似的文档,文档样式结构类似的.同理,流程模板实例为流程实例后,就是具体的一个 ...

  4. 异常SRVE0199E

    后台生成导出exe表格,在tomcat自己环境下完全没问题到websphere环境下保SRVE0199E产生这个问题是因为response.OutputStream已经打开再次打开就报这个异常,前台如 ...

  5. es6 模本字符串拼接方法 ``

    1.字符串拼接  可以使用 es6  ` ` 配合 ${xxx} 具体操作上代码 <!DOCTYPE html> <html lang="en"> < ...

  6. Linux(Ubuntu)使用日记(四)------印象笔记相关使用

    在Ubuntu系统下没有印象笔记官方的客户端,但是这并不能阻拦我们使用印象笔记. 我们一般的的使用习惯: 印象笔记客户端 印象笔记剪藏 Linux下也可以使用两个工具,剪藏的话安装比较简单,印象笔记客 ...

  7. centos7之关于时间和日期以及时间同步的应用

    在CentOS 6版本,时间设置有date.hwclock命令,从CentOS 7开始,使用了一个新的命令timedatectl. 基本概念: 一.GMT.UTC.CST.DST 时间 UTC 整个地 ...

  8. mysql-笔记--增删改查

    查看数据库:可以使用 show databases; 命令查看已经创建了哪些数据库 指定数据库:在登录后使用 use 语句指定, 命令: use 数据库名;要对一个数据库进行操作, 必须先选择该数据库 ...

  9. 数据分析---《Python for Data Analysis》学习笔记【01】

    <Python for Data Analysis>一书由Wes Mckinney所著,中文译名是<利用Python进行数据分析>.这里记录一下学习过程,其中有些方法和书中不同 ...

  10. Redis系列八:redis主从复制和哨兵

    一.Redis主从复制 主从复制:主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性 1. 主从复制的相关操作 a,配置主从复制方式一.新增redis6380.conf, ...