一切福田,不離方寸,從心而覓,感無不通。

Category Archives: Programming Language

深入探析c# Socket

  最近浏览了几篇有关Socket发送消息的文章,发现大家对Socket Send方法理解有所偏差,现将自己在开发过程中对Socket的领悟写出来,以供大家参考。   (一)架构   基于TCP协议的Socket通信,架构类似于B/S架构,一个Socket通信服务器,多个Socket通信客户端。Socket通信服务器启动时,会建立一个侦听Socket,侦听Socket将侦听到的Socket连接传给接受Socket,然后由接受Socket完成接受、发送消息,当Socket存在异常时,断开连接。在实际开发项目中,往往要求Socket通信服务器能提供高效、稳定的服务,一般会用到以下技术:双工通信、完成端口、SAEA、池、多线程、异步等。特别是池,用的比较多,池一般包括一下几种: 1)Buffer池,用于集中管控Socket缓冲区,防止内存碎片。 2)SAEA池,用于集中管控Socket,重复利用Socket。 3)SQL池,用于分离网络服务层与数据访问层(SQL的执行效率远远低于网络层执行效率)。 4)线程池,用于从线程池中调用空闲线程执行业务逻辑,进一步提高网络层运行效率。   (二)Send   主服务器接受Socket为一端口,客户端Socket为一端口,这两个端口通过TCP协议建立连接,通信基础系统负责管理此连接,它有两个功能:   1)发送消息   2)接受消息   Socket的Send方法,并非大家想象中的从一个端口发送消息到另一个端口,它仅仅是拷贝数据到基础系统的发送缓冲区,然后由基础系统将发送缓冲区的数据到连接的另一端口。值得一说的是,这里的拷贝数据与异步发送消息的拷贝是不一样的,同步发送的拷贝,是直接拷贝数据到基础系统缓冲区,拷贝完成后返回,在拷贝的过程中,执行线程会IO等待, 此种拷贝与Socket自带的Buffer空间无关,但异步发送消息的拷贝,是将Socket自带的Buffer空间内的所有数据,拷贝到基础系统发送缓冲区,并立即返回,执行线程无需IO等待,所以异步发送在发送前必须执行SetBuffer方法,拷贝完成后,会触发你自定义回调函数ProcessSend,在ProcessSend方法中,调用SetBuffer方法,重新初始化Buffer空间。       口说无凭,下面给个例子:   服务器端: 客户端: 解释:   客户端第一次发送数据:1234567890。 客户端第一个接受数据:1234567890,该数据由服务端用Send同步方法发送返回。 客户端第二个接受数据:1234567890,该数据由服务端用Send异步方法发送返回。   以上似乎没什么异常,好,接下来,我只发送abc。 客户端第一个接受数据:abc,理所当然,没什么问题。 客户端第二个接受数据:abc4567890!为什么呢?应该是abc才对呀!   好,现在为大家解释一下: 异步发送是将其Buffer空间中所有数据拷贝到基础系统发送缓冲区,第一次拷贝1234567890到发送缓冲区,所以收到1234567890,第二次拷贝abc到发送缓冲区,替换了先前的123,所以收到abc4567890,大家明白的?   源码:     BufferManager

      SocketAsyncEventArgsPool

     

      Server

        Program

http://www.cnblogs.com/tianzhiliang/archive/2010/09/08/1821623.html

龙生   21 Apr 2012
View Details

C#的Socket程序(TCP)

其实只要用到Socket联接,基本上就得使用Thread,是交叉使用的。C#封装的Socket用法基本上不算很复杂,只是不知道托管之后的Socket有没有其他性能或者安全上的问题。在C#里面能找到的最底层的操作也就是socket了,概念不做解释。程序模型如下:WinForm程序 : 启动端口侦听;监视Socket联接情况;定期关闭不活动的联接;Listener:处理Socket的Accept函数,侦听新链接,建立新Thread来处理这些联接(Connection)。Connection:处理具体的每一个联接的会话。 1:WinForm如何启动一个新的线程来启动Listener://start the serverprivate void btn_startServer_Click(object sender, EventArgs e){//this.btn_startServer.Enabled = false;Thread _createServer = new Thread(new ThreadStart(WaitForConnect));_createServer.Start();}//wait all connectionsprivate void WaitForConnect(){SocketListener listener = new SocketListener(Convert.ToInt32(this.txt_port.Text));listener.StartListening();}因为侦听联接是一个循环等待的函数,所以不可能在WinForm的线程里面直接执行,不然Winform也就是无法继续任何操作了,所以才指定一个新的线程来执行这个函数,启动侦听循环。这一个新的线程是比较简单的,基本上没有启动的参数,直接指定处理函数就可以了。2:Listener如何启动循环侦听,并且启动新的带有参数的线程来处理Socket联接会话。先看如何建立侦听:(StartListening函数)IPEndPoint localEndPoint = new IPEndPoint(_ipAddress, _port);// Create a TCP/IP socket. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// Bind the socket to the local endpoint and listen for incoming connections. try{listener.Bind(localEndPoint);listener.Listen(20);//20 trucks // Start listening for connections. while (true){// here will be suspended while waiting for a new connection. Socket connection = listener.Accept();Logger.Log("Connect", connection.RemoteEndPoint.ToString());//log it, new connection……}}……基本步骤比较简单:建立本机的IPEndPoint对象,表示以本机为服务器,在指定端口侦听;然后绑定到一个侦听Socket上;进入while循环,等待新的联接;如果有新的联接,那么建立新的socket来对应这个联接的会话。值得注意的就是这一句联接代码:listener.Accept()。执行这一句的时候,程序就在这个地方等待,直到有新的联检请求的时候程序才会执行下一句。这是同步执行,当然也可以异步执行。 新的联接Socket建立了(Accept之后),对于这些新的socket该怎么办呢?他们依然是一个循环等待,所以依然需要建立新的Thread给这些Socket去处理会话(接收/发送消息),而这个Thread就要接收参数了。Thread本身是不能接收参数的,为了让它可以接收参数,可以采用定义新类,添加参数作为属性的方法来解决。因为每一个Socket是一个Connection周期,所以我定义了这么一个类public class Connection。这个类至少有这样一个构造函数public Connection(Socket socket); 之所以这么做,就是为了把Socket参数传给这个Connection对象,然后好让Listener启动这个Thread的时候,Thread可以知道他正在处理哪一个Socket。具体处理的方法:(在Listener的StartListening函数,ocket connection […]

龙生   21 Apr 2012
View Details

LINQ&EF任我行(二)--LinQ to Object (转)

LinQ to Objects是LinQ家庭的核心,其它的LinQ也使用了与LinQ to Objects相同的查询句法。最终编译器都是把LinQ句法翻译成扩展方法的链式表达式,同时把扩展方法中的lambda表达式转换成匿名类中的匿名方法,然后再把查询表达式编译成MSIL。 LinQ to SQL、LinQ to DataSets、LinQ to Entities和LinQ to XML则不是把查询表达式转换成MSIL,而是把查询表达式树转换成相应的特定查询语言。LinQ to SQL会生成T-SQL,LinQ to Entities会生成eSQL,LinQ to XML会生成XPath语句等。 LinQ标准查询操作符列表     《图1》 在VS2008及以后的版本中提供了LinQ的查询样例程序。 \Programe Files\Microsoft Visual Studio 2008(10.0 VS2010)\Samples\1033文件夹下有个压缩包CSharpSamples.zip,解压它,继续打开其中的文件夹 .\LinqSamples\SampleQueries\SampleQueries.sln,打开此解决方案,运行该项目,界面如下     《图2》 在左边选择示例,右侧上方会出现相应的LinQ代码,右侧下方会出现代码的运行结果。通过这个样例程序,我们可以学习LinQ的各种用法。 下面我们来学习LinQ常用操作符 一、筛选操作符Where 根据谓词对源序列的内容进行筛选,类似于SQL中的where子句。 1.简单where表达式 使用扩展方法 var query1 = CustomerList.Where(c => c.Country == “USA”); 使用查询表达式语法 query1 = from c in CustomerList where c.Country == “USA” select c; 使用扩展方法需要向where方法中传入lambda表达式。 2.复合where表达式 所谓的复合where表达式就是使用&&或||操作符对数据进行筛选 使用扩展方法 var query2 = CustomerList.Where(c => c.Country == “USA” &&   c.Orders.Any()); 使用查询表达式语法 query2 = from c in CustomerList where c.Country == “USA” […]

龙生   18 Apr 2012
View Details

ASP内置对象 Request对象

集合 Request.ClientCertificate(key[SubField])所有客户证书的信息的集合。对于Key,该集合具有如下的关键字: Subject证书的主题。包含所有关于证书收据的信息。能和所有的子域后缀一起使用。 Issuer证书的发行人。包含所有关于证书验证的信息。除了CN外,能和所有的子域后缀一起使用。 VadidFrom证书发行的日期。使用VBScript格式。 ValidUntil该证书不在有效的时间。 SerialNumber包含该证书的序列号。 Certificate包含整个证书内容的二进制流,使用ASN.1格式。 对于SubField,Subject和Issuer关键字可以具有如下的子域后缀:(比如:SubjectOU或IssuerL) C起源国家。 O公司或组织名称。 OU组织单元。 CN用户的常规名称。 L局部。 S州(或省)。 T个人或公司的标题。 GN给定名称。 I初始。 当文件cervbs.inc(VBScript使用)或cerjavas.inc(Jscript使用)通过使用#INCLUDE导向包含在你的Active Server Page里时,下面两个标志可以使用: ceCertPresent指明客户证书是否存在,其值为TRUE或FALSE。 ceUnrecongnizedIssure指明在该链表中的最后的证书的发行者是否未知,其值为TRUE或FALSE。 Request.Cookies(Cookie[(key).Attribute]) Cookie的集合。允许获得浏览器的Cookie。Cookie指明返回那一个Cookie。Key用于从Cookie字典中返回具有某一关键字的Cookie值。对于Attribute,你能使用属性HasKeys来确定某一Cookie是否具有子关键字。HasKeys的值为TRUE或FALSE。 Request.Form(Parameter)[(Index).Count] 填写在HTML的表单中所有的数据的集合。Parameter是在HTML表单中某一元素的名称。当某一参数具有不止一个值(比如,当在<SELECT>中使用MULTIPLE属性时)时,使用Index。当某一参数具有多值时,Count指明多值个数。 Request.QueryString(Varible)[(Index).Count] 查询字符串的所有值的集合。Varible是在查询字符串某一变量的名称。当某一变量具有多于一个值时,使用Index。当某一参数具有多值时,Count指明值的个数。 Request.ServerVaribles(Server Environment Variable) 环境变量的集合。允许读取HTTP头。你可以通过使用HTTP_前缀来读取任何头信息。比如,HTTP_USER_AGENT接受客户代理HTTP头(浏览器类型)。除此外,你可以使用下表所示的变量获得任何环境信息。 ALL_HTTP客户端发送的所有HTTP标头,他的结果都有前缀HTTP_。 ALL_RAW客户端发送的所有HTTP标头,其结果和客户端发送时一样,没有前缀HTTP_ APPL_MD_PATH应用程序的元数据库路径。 APPL_PHYSICAL_PATH与应用程序元数据库路径相应的物理路径。 AUTH_PASSWORD当使用基本验证模式时,客户在密码对话框中输入的密码。 AUTH_TYPE这是用户访问受保护的脚本时,服务器用于检验用户的验证方法。 AUTH_USER代验证的用户名。 CERT_COOKIE唯一的客户证书ID号。 CERT_FLAG客户证书标志,如有客户端证书,则bit0为0。如果客户端证书验证无效,bit1被设置为1。 CERT_ISSUER用户证书中的发行者字段。 CERT_KEYSIZE安全套接字层连接关键字的位数,如128。 CERT_SECRETKEYSIZE服务器验证私人关键字的位数。如1024。 CERT_SERIALNUMBER客户证书的序列号字段。 CERT_SERVER_ISSUER服务器证书的发行者字段 CERT_SERVER_SUBJECT服务器证书的主题字段。 CERT_SUBJECT客户端证书的主题字段。 CONTENT_LENGTH客户端发出内容的长度。 CONTENT_TYPE客户发送的form内容或HTTP PUT的数据类型。 GATEWAY_INTERFACE服务器使用的网关界面。 HTTPS如果请求穿过安全通道(SSL),则返回ON。如果请求来自非安全通道,则返回OFF。 HTTPS_KEYSIZE安全套接字层连接关键字的位数,如128。 HTTPS_SECRETKEYSIZE服务器验证私人关键字的位数。如1024。 HTTPS_SERVER_ISSUER服务器证书的发行者字段。 HTTPS_SERVER_SUBJECT服务器证书的主题字段。 INSTANCE_IDIIS实例的ID号。 INSTANCE_META_PATH响应请求的IIS实例的元数据库路径。 LOCAL_ADDR返回接受请求的服务器地址。 LOGON_USER用户登录Windows NT的帐号 PATH_INFO客户端提供的路径信息。 PATH_TRANSLATED通过由虚拟至物理的映射后得到的路径。 QUERY_STRING查询字符串内容。 REMOTE_ADDR发出请求的远程主机的IP地址。 REMOTE_HOST发出请求的远程主机名称。 REQUEST_METHOD提出请求的方法。比如GET、HEAD、POST等等。 SCRIPT_NAME执行脚本的名称。 SERVER_NAME服务器的主机名、DNS地址或IP地址。 SERVER_PORT接受请求的服务器端口号。 SERVER_PORT_SECURE如果接受请求的服务器端口为安全端口时,则为1,否则为0。 SERVER_PROTOCOL服务器使用的协议的名称和版本。 SERVER_SOFTWARE应答请求并运行网关的服务器软件的名称和版本。 URL提供URL的基本部分。  方法 Request.BinaryRead(Count) 接收一个HTML表单的未经过处理的内容。当调用此方法时,Count指明要接收多少字节。在调用此方法后,Count指明实际上接收到多少个字节。 属性 Request.TotalBytes 查询体的长度,以字节为单位。

龙生   11 Apr 2012
View Details

清除页面缓存

当使用ASP进行Web编程时,你发现确实修改了程序代码,确认没有改错,却发现输出的Webyemi8an没有变化,这就是服务端将此ASP文件加入了页面缓存。    清楚页面缓存有一下几种方法;    1.在ASP页面首部加入一下代码:      Response.Buffer=True      Response.ExpiresAbsolute=Now()-1      Response.Expires=0      Response.CacheControl=“no-cache”      Response.AddHeader “Pragma”,“no-Cache”    2.在HTML代码中加入下面的代码,不过这些代码似乎不能解决刷新无效的问题,因为这些代码只是针对客户端的页面缓存而已,只具有清楚客户端的页面缓存的功能。      <HEAD>        <META HTTP-EQUIV="Pragma" CONTENT="no-cache">        <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">        <META HTTP-EQUIV="Expires" CONTENT="no-cache">      </HEAD>    3.如果一个ASP文件是url.asp,那么在访问的时候,脚本链接应该为:      <input type="button" onclick="window.location.href=’url.asp?’+Math.random()" value="提交"/> 

龙生   11 Apr 2012
View Details

ScriptManager.RegisterStartupScript失效的解决方案

今天在项目中一个页面使用 System.Web.UI.ScriptManager.RegisterStartupScript(this, GetType(), "js", "alert('OK');", true);的时候发现没用,检查发现脚本没用注册到页面, check页面发现了问题,<form method="post"> 没用ruanat,更详细的信息请参看MSDN关于这个方法参数的介绍

龙生   11 Apr 2012
View Details

VS2010安装项目的系统必备中添加.NET 2.0

  VS2010安装项目的系统必备中没有.NET 2.0,不过我们可以从VS2008的程序文件中找到 .NET 2.0 的系统必备安装包。     安装了VS2008 的 C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages 下的 DotNetFX 文件夹,就是 .NET 2.0 的系统必备安装包。把 DotNetFX 文件夹复制到安装了 VS2010 的 C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages下,然后在VS2010中就可以选择 .NET 2.0 的系统必备了。   原文:http://www.cnblogs.com/anjou/archive/2011/05/08/2040675.html

龙生   31 Mar 2012
View Details

Page.ClientScript.RegisterStartupScript 与 Page.ClientScript.RegisterClientScriptBlock 之间的区别

 Page.ClientScript.RegisterStartupScript 与 Page.ClientScript.RegisterClientScriptBlock 被用来注册脚本块。第一个是 RegisterStartupScript 方法。当您有一个想要在页面加载时启动的 JavaScript 函数时,最好使用该类。就此列举一例,在 Visual Studio 2005 中创建一个包含两个按钮的 ASP.NET 页面。Button1 和 Button2 分别为这两个按钮的 ID。然后,在 Page_Load 事件内部嵌入以下代码  C#:

RegisterStartupScript 方法的两个可能结构如下:   • RegisterStartupScript (type, key, script) • RegisterStartupScript (type, key, script, script tag specification) 在上例中,您指定了类型 Me.GetType()、关键字及包含的脚本,然后是一个值为 True 的布尔值(以便 .NET 自动使用 <script> 标记将脚本嵌入 ASP.NET 页面中)。Page.ClientScript.RegisterStartupScript 与 Page.ClientScript.RegisterClientScriptBlock 之间的区别 主要区别在于:RegisterStartupScript 方法是将 JavaScript 嵌入到 ASP.NET 页面的底部,恰好位于关闭元素 </form> 的前面。RegisterClientScriptBlock方法是将 JavaScript 嵌入到页面中开启元素 <form> 的紧后面。那么,这有何不同呢?正如我们将要看到的,这有很大的不同。 就此列举一例,以下是在页面加载到浏览器时,将焦点置于该页面上的一个文本框中的方法 – 使用利用了 RegisterStartupScript 方法:

由于在浏览器运行到页面底部并执行此小段 JavaScript 时,就已生成了页面上的文本框,并已将其放到了页面中,因此,此方法运行正常。但是,如果不按照上述方法,而编写如下代码(使用 RegisterClientScriptBlock 方法):

文本框控件将不会获得焦点,且会在页面上生成一个 JavaScript 错误(如图 1 所示)。   图 1. 执行 JavaScript 时出错 出错的原因在于,浏览器将先遇到 JavaScript,而后文本框才会出现在页面中。因此,JavaScript 将无法找到 txtText。 原文出处:http://blog.csdn.net/jiahello/archive/2009/06/29/4305855.aspx 

龙生   29 Mar 2012
View Details

c#中const与readonly区别

 const 的概念就是一个包含不能修改的值的变量。

龙生   29 Mar 2012
View Details

IIS7配置PHP图解

  PHP5.2.17 官方下载: http://windows.php.net/downloads/releases/php-5.4.3-Win32-VC9-x86.zip 首先安装好IIS7 安装的时候 要注意三个地方打得勾   注:   CGI  会在IIS7+PHP_5.3.5的环境中用到        ISAPI扩展和ISAPI筛选器 用在IIS7+PHP_5.2.17 下面开始添加IIS的PHP支持  IIS7+PHP_5.3.5 1.  将下载回来的php_5.3.5解压到 C:\php目录(也可以放在其他地方,但是后面应该做相应修改)  2.  将php.ini-development改名为php.ini 3.  修改php.ini 查找date.timezone  修改为date.timezone = “Asia/Shanghai”(这里必须改,不然会出警告)   找到Windows Extensions开启 所需模块,如:php_curl.dll  php_mysql.dll   php_mysqli.dll   php_xmlrpc.dll   只要去掉前面的 分号 保存就可以了 4.  添加<模块映射>       这里的路径按你的实际情况填写. 5.  在网站根目录新建一个phpinfo.php的文本文件 内容为: <?php phpinfo();?> 6.  测试,打开浏览器看结果:localhost/phpinfo.php,如果能看到类似下面的页面就说明你成功了: 好了,到现在 已经可以成功的运行PHP程序了. IIS7+PHP_5.2.17 于之前安装IIS的时候已经选上了isapi扩展和isapi筛选,这里就不用另外再添加角色服务了,直接开始 先修改php.ini文件.. 把c:\php下的php.ini-dist (需先设置显示扩展名)改名成php.ini,用记事本打开 找到extension_dir = “./”,然后把里面的./改成c:\php(根据自己的实际情况修改路径) 1.  添加应用程序池   2. 添加isapi和cgi限制   3. 添加isapi筛选器   4.  添加脚本映射    5.  测试(之前已经创建了phpinfo.php)   跟之前一样 打开localhost/phpinfo.php 查看效果:  

龙生   23 Mar 2012
View Details
1 166 167 168 174