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
- C#-基础加强(2)
- C#-基础加强(1)
- Java高新基础加强(2)
- 黑马程序员----java基础加强(2)
- JAVA 基础加强2
- 基础加强-2
- c#基础加强2
- html基础加强2
- html基础加强2
- 基础加强(概述)
- 基础加强 (一)
- 基础加强(二)
- java基础加强2--注解
- Java基础加强总结(2)
- 黑马程序员----基础加强2
- 黑马程序员-------基础加强2
- 黑马程序员-基础加强2
- java基础加强(一)
- Service和Thread的关系
- Spring AOP之AspectJ
- C++字符串总结
- Leetcode|Combination Sum III[回溯]
- awk
- C#-基础加强(2)
- HDOJ 1283 最简单的计算机
- 爬虫Spider
- Android之路
- 写一个函数,计算4 000 000 000 以内的最大的那个f(n)=n的值
- Java 中的成员内部类
- lock synchronized 区别
- B样条绘制
- zoj 3460 Missile 【二分 + 二分图匹配】 【经典建模】 【二分 + 最大流】