C#-基础加强(2)

来源:互联网 发布:电脑接口转换器 知乎 编辑:程序博客网 时间:2024/05/21 12:48

1.回顾:上篇学习了很多,C# io知识,序列化等

2.这篇将学习 Socket和服务器软件

3.Socket

(1)      Socket 的使用

同上,上面实现简单的服务器端的编写,下面是客户端,同样发送和接收方法和服务器端一样。

     

 connSoc = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            IPAddress ipaddress =IPAddress.Parse(ComConst.ipAddress);            IPEndPoint ipPoint = newIPEndPoint(ipaddress, ComConst.ipPort);           //连接服务器IPEndPoint            connSoc.Connect(ipPoint);            textBox1.Text += "登陆成功"+"\r\n";

 聊天程序

  见项目SocketServer

 

4.服务器软件

(1) 服务器软件和Socket使用

浏览器和服务器通信也是通过类似于Socket(套接字)、报文实现的,浏览器向服务器端发送报文,服务器软件接收到了以后,开始解析,同时使用长连接来实现,浏览器的请求,从而给浏览器返回报头和以流式的方式发给资源比如图片,js,css,html等。如果是动态页面,则需要用反射的原理来实现,从而加载出资源,以流式方式发给浏览器。


5.服务器软件实现代码

using System;using System.Collections.Generic;using System.Threading;using System.Net;using System.Net.Sockets;using System.Text;using System.IO;using System.Reflection; namespace C0710_OurSimpleHttpWebServer{    /// <summary>    /// 与客户端的 连接通信类(包含了一个 与客户端通信的 套接字,和线程)    ///</summary>   public class ConnectionClient   {       Socket sokMsg;//通信套接字       DGShowMsg dgShowMsg;//负责向主窗体文本框显示消息的方法委托       DGShowMsg dgRemoveConnection;// 负责 从主窗体 中移除 当前连接对象       Thread threadMsg;//通信线程        #region 01.构造函数       /// <summary>       ///       /// </summary>       /// <param name="sokMsg">通信套接字</param>       /// <param name="dgShowMsg">向主窗体文本框显示消息的方法委托</param>       public ConnectionClient(Socket sokMsg, DGShowMsg dgShowMsg, DGShowMsgdgRemoveConnection)       {           this.sokMsg = sokMsg;           this.dgShowMsg = dgShowMsg;           this.dgRemoveConnection = dgRemoveConnection;           //启动一个 负责接收 浏览器发送来的 请求报文的 线程           this.threadMsg = new Thread(RecMsg);           this.threadMsg.IsBackground = true;           this.threadMsg.Start();       }       #endregion        bool isRec = true;//循环接收消息标志位        #region 02负责监听浏览器发送来的请求报文       /// <summary>       /// 02负责监听浏览器发送来的请求报文       /// </summary>       void RecMsg()       {           while (isRec)           {                try                {                    byte[] arrMsg = newbyte[1024 * 1024 * 2];                    //接收 对应 客户端发来的请求报文                    int length =sokMsg.Receive(arrMsg);                    //将接收到的消息数组里真实消息转成字符串                    string strMsg =System.Text.Encoding.UTF8.GetString(arrMsg, 0, length);                   //通过委托 显示消息到 窗体的文本框                    dgShowMsg(strMsg);                   //-------------------------------分析请求报文-----------------------------------------                    //根据请求报文里的换行符,将请求报文的每一行都存入数组元素                    string [] arrStr =strMsg.Replace("\r\n", "黀").Split('黀');                    //将第一行的数据,根据空格符 分割成数组                    string[] firstRow =arrStr[0].Split(' ');                    //从第一行 第二个元素中 获得浏览器 请求的页面路径                    string requestFile =firstRow[1];                    ExcuteRequest(requestFile);                    //传入 GetResponseEntity方法来获得生成的要返回给浏览器的响应报文                    //string responseStr =ExcuteRequest(requestFile);                    //将响应报文发送回浏览器                    //Send(responseStr);                 }                catch (Exception ex)                {                    isRec = false;                    //从主窗体中 移除 下拉框中对应的客户端选择项,同时 移除 集合中对应的 ConnectionClient对象                    dgRemoveConnection(sokMsg.RemoteEndPoint.ToString());                }           }       }       #endregion        #region 03.根据请求的页面路径来 调用不同的方法 处理,并最终生成响应报文发送回浏览器       /// <summary>       /// 03.根据请求的页面路径来 调用不同的方法 处理,并最终生成响应报文发送回浏览器       /// </summary>       /// <param name="filePath">请求的页面路径</param>       void ExcuteRequest(string filePath)       {           string fileExtension = System.IO.Path.GetExtension(filePath);//获得被请求页面的 文件后缀           switch (fileExtension)           {                case ".html":                case ".htm":                case ".css":                case ".js":                    //调用处理 静态页面的方法                    ExcuteStaticPage(filePath,fileExtension);                    break;                case ".jpg":                    //调用处理 图片的方法                    ExcuteImg(filePath,fileExtension);                    break;                case ".aspx":                case ".jsp":                case ".php":                    //调用处理 动态页面的方法                    ExcuteDymPage(filePath,fileExtension);                    break;           }       }       #endregion        #region 04.处理静态页面 +string ExcuteStaticPage(stringrequestPath)       /// <summary>       /// 处理静态页面       /// </summary>       /// <param name="requestPath">请求的页面路径</param>       /// <returns></returns>       public void ExcuteStaticPage(string requestPath,string extentionName)       {           StringBuilder sb = new StringBuilder();           //获得请求文件的文件夹的物理路径           string dataDir = AppDomain.CurrentDomain.BaseDirectory;           if (dataDir.EndsWith(@"\bin\Debug\") ||dataDir.EndsWith(@"\bin\Release\"))           {                dataDir =System.IO.Directory.GetParent(dataDir).Parent.Parent.FullName;           }           //获得请求文件的物理路径(绝对路径)           string phyPath = dataDir + "" + requestPath;           //读取静态页面的内容           string fileContent = System.IO.File.ReadAllText(phyPath);           //获得 静态页面内容的 字节数组 -- 就是 响应体内容            byte[] fileArr =System.Text.Encoding.UTF8.GetBytes(fileContent);           //获得 响应报文头           string responseHeader = GetResponseHeader(fileArr.Length,extentionName);           byte[] arrHeader = System.Text.Encoding.UTF8.GetBytes(responseHeader);           //发送 响应报文头 回浏览器           sokMsg.Send(arrHeader);           //发送 响应报文体 回浏览器           sokMsg.Send(fileArr);       }       #endregion        #region 05.根据浏览器请求报文中 请求的图片,返回响应报文 +string ExcuteImg(stringrequestPath, string extentionName)       /// <summary>       /// 根据浏览器请求报文中 请求的图片,返回响应报文       /// </summary>       /// <param name="requestPath">请求的图片路径</param>       /// <returns></returns>       public void ExcuteImg(string requestPath, string extentionName)       {           //获得请求文件的文件夹的物理路径           string dataDir = AppDomain.CurrentDomain.BaseDirectory;           if (dataDir.EndsWith(@"\bin\Debug\") || dataDir.EndsWith(@"\bin\Release\"))           {                dataDir =System.IO.Directory.GetParent(dataDir).Parent.Parent.FullName;           }           //获得请求文件的物理路径(绝对路径)           string phyPath = dataDir + "" + requestPath;           int imgLength = 0;//图片的真实大小           byte[] fileAr;           //读取图片的内容           using (FileStream fs = new FileStream(phyPath, FileMode.Open))           {                fileAr = new byte[fs.Length];                imgLength = fs.Read(fileAr, 0,fileAr.Length);           }           //获得 响应报文头           string responseHeader = GetResponseHeader(imgLength, extentionName);           byte[] arrHeader = System.Text.Encoding.UTF8.GetBytes(responseHeader);           //发送 响应报文头 回浏览器           sokMsg.Send(arrHeader);           //发送 响应报文体 回浏览器           sokMsg.Send(fileAr, imgLength, SocketFlags.None);       }       #endregion        #region 06.根据浏览器请求报文中 请求的动态页面,返回响应报文 +stringExcuteDymPage(string requestPath, string extentionName)       /// <summary>       /// 根据浏览器请求报文中 请求的动态页面,返回响应报文       /// </summary>       /// <param name="requestPath">请求的动态页面路径</param>       /// <returns></returns>       public void ExcuteDymPage(string requestPath, string extentionName)       {           //反射:创建类的对象--1.类名(类的全名称-包括命名空间名称命名空间名称.页面类名)           //获得页面类名           string pageClassName =System.IO.Path.GetFileNameWithoutExtension(requestPath);           //获得程序集的纯的名字           string assmblyName = Assembly.GetExecutingAssembly().GetName().Name;           //获得页面类的全名称           pageClassName = assmblyName + "." + pageClassName;           //通过反射创建页面类对象           object pageObj =Assembly.GetExecutingAssembly().CreateInstance(pageClassName);           IHttpHandler page = pageObj as IHttpHandler;           byte[] fileArr=null;           if (page != null)           {                //获得动态页面 执行之后返回的 html代码                string htmlStr =page.ProcessRequest();                //响应报文体 数据                fileArr =System.Text.Encoding.UTF8.GetBytes(htmlStr);           }           //获得 响应报文头           string responseHeader = GetResponseHeader(fileArr.Length,extentionName);           byte[] arrHeader = System.Text.Encoding.UTF8.GetBytes(responseHeader);           //发送 响应报文头 回浏览器           sokMsg.Send(arrHeader);           //发送 响应报文体 回浏览器           sokMsg.Send(fileArr);       }       #endregion        #region 07.返回响应报文头 +string GetResponseHeader(stringrequestPath, int contentLength, string extentionName)       /// <summary>       /// 返回响应报文头       /// </summary>       /// <param name="contentLength"></param>       /// <param name="extentionName"></param>       /// <returns></returns>       public string GetResponseHeader(int contentLength, string extentionName)       {           System.Text.StringBuilder sbHeader = new StringBuilder();           sbHeader.Append("HTTP/1.1 200 OK\r\n");           sbHeader.Append("Content-Length: " + contentLength +"\r\n");           sbHeader.Append("Content-Type: " +GetResponseContentType(extentionName) + ";charset=utf-8\r\n\r\n");           return sbHeader.ToString();       }       #endregion        #region 08根据后缀名 获得 响应报文 中的内容类型 -stringGetResponseContentType(string extentionName)       /// <summary>       /// 根据后缀名 获得 响应报文 中的内容类型       /// </summary>       /// <param name="extentionName">后缀名</param>       /// <returns></returns>       string GetResponseContentType(string extentionName)       {           switch (extentionName)           {                case ".aspx":                case ".jsp":                case ".php":                case ".html":                case ".htm":                    return"text/html";                case ".css":                    return"text/plain";                case ".js":                    return"text/javascript";                case ".jpg":                    return"image/JPEG";                default:                    return"text/html";           }       }       #endregion              #region 09关闭与客户端连接       /// <summary>       /// 关闭与客户端连接       /// </summary>       public void CloseConnection()       {           isRec = false;       }       #endregion   }}



0 0