网站域名的根目录在哪里,wordpress建一个网站吗,wordpress文章图片默认居中,建设门户网站费用Microsoft.Net Framework为应用程序访问Internet提供了分层的、可扩展的以及受管辖的网络服务#xff0c;其名字空间System.Net和 System.Net.Sockets包含丰富的类可以开发多种网络应用程序。.Net类采用的分层结构允许应用程序在不同的控制级别上访问网络#xff0c;开发人员… Microsoft.Net Framework为应用程序访问Internet提供了分层的、可扩展的以及受管辖的网络服务其名字空间System.Net和 System.Net.Sockets包含丰富的类可以开发多种网络应用程序。.Net类采用的分层结构允许应用程序在不同的控制级别上访问网络开发人员可以根据需要选择针对不同的级别编制程序这些级别几乎囊括了Internet的所有需要--从socket套接字到普通的请求/响应更重要的是这种分层是可以扩展的能够适应Internet不断扩展的需要。 抛开ISO/OSI模型的7层构架单从TCP/IP模型上的逻辑层面上看.Net类可以视为包含3个层次请求/响应层、应用协议层、传输层。 WebReqeust和WebResponse 代表了请求/响应层支持Http、Tcp和Udp的类组成了应用协议层而Socket类处于传输层。可以如下示意 可见传输层位于这个结构的最底层当其上面的应用协议层和请求/响应层不能满足应用程序的特殊需要时就需要使用这一层进行Socket套接字编程。 而在.Net中System.Net.Sockets 命名空间为需要严密控制网络访问的开发人员提供了 Windows Sockets (Winsock) 接口的托管实现。System.Net 命名空间中的所有其他网络访问类都建立在该套接字Socket实现之上如TCPClient、TCPListener 和 UDPClient 类封装有关创建到 Internet 的 TCP 和 UDP 连接的详细信息NetworkStream类则提供用于网络访问的基础数据流等常见的许多Internet服务都可以见到Socket的踪影如 Telnet、Http、Email、Echo等这些服务尽管通讯协议Protocol的定义不同但是其基础的传输都是采用的Socket。 其实Socket可以象流Stream一样被视为一个数据通道这个通道架设在应用程序端客户端和远程服务器端之间而后数据的读取接收和写入发送均针对这个通道来进行。 可见在应用程序端或者服务器端创建了Socket对象之后就可以使用Send/SentTo方法将数据发送到连接的Socket, 或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据 针对Socket编程.NET 框架的 Socket 类是 Winsock32 API 提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法大多数情况下Socket 类方法只是将数据封送到它们的本机 Win32 副本中并处理任何必要的安全检查。如果你熟悉Winsock API函数那么用Socket类编写网络程序会非常容易当然如果你不曾接触过也不会太困难跟随下面的解说你会发觉使用Socket类开发 windows 网络应用程序原来有规可寻它们在大多数情况下遵循大致相同的步骤。 在使用之前你需要首先创建Socket对象的实例这可以通过Socket类的构造方法来实现 public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType); 其中 AddressFamily 参数指定 Socket 使用的寻址方案 socketType 参数指定 Socket 的类型 protocolType 参数指定 Socket 使用的协议。 下面的示例语句创建一个 Socket它可用于在基于 TCP/IP 的网络如 Internet上通讯。 Socket s new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 若要使用 UDP 而不是 TCP需要更改协议类型如下面的示例所示 Socket s new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 一旦创建 Socket在客户端你将可以通过Connect方法连接到指定的服务器并通过Send/SendTo方法向远程服务器发送数据而后可以通过 Receive/ReceiveFrom从服务端接收数据 而在服务器端你需要使用Bind方法绑定所指定的接口使Socket与一个本地终结点相联并通过Listen方法侦听该接口上的请求当侦听到用户端的连接时调用Accept完成连接的操作创建新的Socket以处理传入的连接请求。使用完 Socket 后记住使用 Shutdown 方法禁用 Socket并使用 Close 方法关闭 Socket。其间用到的方法/函数有 Socket.Connect方法:建立到远程设备的连接 public void Connect(EndPoint remoteEP)有重载方法 Socket.Send 方法:从数据中的指示位置开始将数据发送到连接的 Socket。 public int Send(byte[], int, SocketFlags);(有重载方法) Socket.SendTo 方法 将数据发送到特定终结点。 public int SendTo(byte[], EndPoint);有重载方法 Socket.Receive方法:将数据从连接的 Socket 接收到接收缓冲区的特定位置。 public int Receive(byte[],int,SocketFlags); Socket.ReceiveFrom方法接收数据缓冲区中特定位置的数据并存储终结点。 public int ReceiveFrom(byte[], int, SocketFlags, ref EndPoint); Socket.Bind 方法使 Socket 与一个本地终结点相关联 //Bind :捆绑 public void Bind( EndPoint localEP ); Socket.Listen方法将 Socket 置于侦听状态。 public void Listen( int backlog ); Socket.Accept方法:创建新的 Socket 以处理传入的连接请求。 public Socket Accept(); Socket.Shutdown方法:禁用某 Socket 上的发送和接收 public void Shutdown( SocketShutdown how ); Socket.Close方法:强制 Socket 连接关闭 public void Close(); 可以看出以上许多方法包含EndPoint类型的参数在Internet中TCP/IP 使用一个网络地址和一个服务端口号来唯一标识设备。网络地址标识网络上的特定设备端口号标识要连接到的该设备上的特定服务。网络地址和服务端口的组合称为终结点在 .NET 框架中正是由 EndPoint 类表示这个终结点它提供表示网络资源或服务的抽象用以标志网络地址等信息。.Net同时也为每个受支持的地址族定义了 EndPoint 的子代对于 IP 地址族该类为 IPEndPoint。IPEndPoint 类包含应用程序连接到主机上的服务所需的主机和端口信息通过组合服务的主机IP地址和端口号IPEndPoint 类形成到服务的连接点。 用到IPEndPoint类的时候就不可避免地涉及到计算机IP地址.Net中有两种类可以得到IP地址实例 IPAddress类IPAddress 类包含计算机在 IP 网络上的地址。其Parse方法可将 IP 地址字符串转换为 IPAddress 实例。下面的语句创建一个 IPAddress 实例 IPAddress myIP IPAddress.Parse(192.168.1.2); Dns 类向使用 TCP/IP Internet 服务的应用程序提供域名服务。其Resolve 方法查询 DNS 服务器以将用户友好的域名如host.contoso.com映射到数字形式的 Internet 地址如 192.168.1.1。Resolve方法 返回一个 IPHostEnty 实例该实例包含所请求名称的地址和别名的列表。大多数情况下可以使用 AddressList 数组中返回的第一个地址。下面的代码获取一个 IPAddress 实例该实例包含服务器 host.contoso.com 的 IP 地址。 IPHostEntry ipHostInfo Dns.Resolve(host.contoso.com); IPAddress ipAddress ipHostInfo.AddressList[0]; 你也可以使用GetHostName方法得到IPHostEntry实例 IPHosntEntry hostInfoDns.GetHostByName(host.contoso.com) 在使用以上方法时你将可能需要处理以下几种异常 SocketException异常访问Socket时操作系统发生错误引发 ArgumentNullException异常参数为空引用引发 ObjectDisposedException异常Socket已经关闭引发 在掌握上面得知识后下面的代码将该服务器主机 host.contoso.com的 IP 地址与端口号组合以便为连接创建远程终结点 IPEndPoint ipe new IPEndPoint(ipAddress,11000); 确定了远程设备的地址并选择了用于连接的端口后应用程序可以尝试建立与远程设备的连接。下面的示例使用现有的 IPEndPoint 实例与远程设备连接并捕获可能引发的异常 try { s.Connect(ipe);//尝试连接 } //处理参数为空引用异常 catch(ArgumentNullException ae) { Console.WriteLine(ArgumentNullException : {0}, ae.ToString()); } //处理操作系统异常 catch(SocketException se) { Console.WriteLine(SocketException : {0}, se.ToString()); } catch(Exception e) { Console.WriteLine(Unexpected exception : {0}, e.ToString()); } 需要知道的是Socket 类支持两种基本模式同步和异步。其区别在于在同步模式中对执行网络操作的函数如 Send 和 Receive的调用一直等到操作完成后才将控制返回给调用程序。在异步模式中这些调用立即返回。 另外很多时候Socket编程视情况不同需要在客户端和服务器端分别予以实现在客户端编制应用程序向服务端指定端口发送请求同时编制服务端应用程序处理该请求这个过程在上面的阐述中已经提及当然并非所有的Socket编程都需要你严格编写这两端程序视应用情况不同你可以在客户端构造出请求字符串服务器相应端口捕获这个请求交由其公用服务程序进行处理。以下事例语句中的字符串就向远程主机提出页面请求 string Get GET / HTTP/1.1\r\nHost: server \r\nConnection: Close\r\n\r\n; 远程主机指定端口接受到这一请求后就可利用其公用服务程序进行处理而不需要另行编制服务器端应用程序。 综合运用以上阐述的使用Visual C#进行Socket网络程序开发的知识下面的程序段完整地实现了Web页面下载功能。用户只需在窗体上输入远程主机名Dns 主机名或以点分隔的四部分表示法格式的 IP 地址和预保存的本地文件名并利用专门提供Http服务的80端口就可以获取远程主机页面并保存在本地机指定文件中。如果保存格式是.htm格式你就可以在Internet浏览器中打开该页面。适当添加代码你甚至可以实现一个简单的浏览器程序。 实现此功能的主要源代码如下 //开始按钮事件 private void button1_Click(object sender, System.EventArgs e) { //取得预保存的文件名 string fileNametextBox3.Text.Trim(); //远程主机 string hostNametextBox1.Text.Trim(); //端口 int portInt32.Parse(textBox2.Text.Trim()); //得到主机信息 IPHostEntry ipInfoDns.GetHostByName(hostName); //取得IPAddress[] IPAddress[] ipAddripInfo.AddressList; //得到ip IPAddress ipipAddr[0]; //组合出远程终结点 IPEndPoint hostEPnew IPEndPoint(ip,port); //创建Socket 实例 Socket socketnew Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); try { //尝试连接 socket.Connect(hostEP); } catch(Exception se) { MessageBox.Show(连接错误se.Message,提示信息 ,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information); } //发送给远程主机的请求内容串 string sendStrGET / HTTP/1.1\r\nHost: hostName \r\nConnection: Close\r\n\r\n; //创建bytes字节数组以转换发送串 byte[] bytesSendStrnew byte[1024]; //将发送内容字符串转换成字节byte数组 bytesSendStrEncoding.ASCII.GetBytes(sendStr); try { //向主机发送请求 socket.Send(bytesSendStr,bytesSendStr.Length,0); } catch(Exception ce) { MessageBox.Show(发送错误:ce.Message,提示信息 ,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information); } //声明接收返回内容的字符串 string recvStr; //声明字节数组一次接收数据的长度为1024字节 byte[] recvBytesnew byte[1024]; //返回实际接收内容的字节数 int bytes0; //循环读取直到接收完所有数据 while(true) { bytessocket.Receive(recvBytes,recvBytes.Length,0); //读取完成后退出循环 if(bytes0) break; //将读取的字节数转换为字符串 recvStrEncoding.ASCII.GetString(recvBytes,0,bytes); } //将所读取的字符串转换为字节数组 byte[] contentEncoding.ASCII.GetBytes(recvStr); try { //创建文件流对象实例 FileStream fsnew FileStream(fileName,FileMode.OpenOrCreate,FileAccess.ReadWrite); //写入文件 fs.Write(content,0,content.Length); } catch(Exception fe) { MessageBox.Show(文件创建/写入错误:fe.Message,提示信息,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information); } //禁用Socket socket.Shutdown(SocketShutdown.Both); //关闭Socket socket.Close(); } } 程序在WindowsXP中文版、.Net Frameworkd 中文正式版、Visual Studio.Net中文正式版下调试通过 C#的Socket程序TCP 其实只要用到Socket联接基本上就得使用Thread是交叉使用的。 C#封装的Socket用法基本上不算很复杂只是不知道托管之后的Socket有没有其他性能或者安全上的问题。 在C#里面能找到的最底层的操作也就是socket了概念不做解释。 程序模型如下 WinForm程序 启动端口侦听监视Socket联接情况定期关闭不活动的联接 Listener处理Socket的Accept函数侦听新链接建立新Thread来处理这些联接Connection。 Connection处理具体的每一个联接的会话。 1WinForm如何启动一个新的线程来启动Listener //start the server private void btn_startServer_Click(object sender, EventArgs e) { //this.btn_startServer.Enabled false; Thread _createServer new Thread(new ThreadStart(WaitForConnect)); _createServer.Start(); } //wait all connections private void WaitForConnect() { SocketListener listener new SocketListener(Convert.ToInt32(this.txt_port.Text)); listener.StartListening(); } 因为侦听联接是一个循环等待的函数所以不可能在WinForm的线程里面直接执行不然Winform也就是无法继续任何操作了所以才指定一个新的线程来执行这个函数启动侦听循环。 这一个新的线程是比较简单的基本上没有启动的参数直接指定处理函数就可以了。 2Listener如何启动循环侦听并且启动新的带有参数的线程来处理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 listener.Accept();之后 Connection gpsCn new Connection(connection); //each socket will be wait for data. keep the connection. Thread thread new Thread(new ThreadStart(gpsCn.WaitForSendData)); thread.Name connection.RemoteEndPoint.ToString(); thread.Start(); 如此一来这个新的socket在Accept之后就在新的Thread中运行了。 3Connection的会话处理 建立了新的Connection也就是socket远程就可以和这个socket进行会话了无非就是send和receive。 现在先看看怎么写的这个线程运行的Connection. WaitForSendData函数 while (true) { bytes new byte[1024]; string data ; //systm will be waiting the msg of receive envet. like Accept(); //here will be suspended while waiting for socket income msg. int bytesRec this._connection.Receive(bytes); _lastConnectTime DateTime.Now; if (bytesRec 0)//close envent { Logger.Log(Close Connection, _connection.RemoteEndPoint.ToString()); break; } data Encoding.ASCII.GetString(bytes, 0, bytesRec); //…….handle your data. } 可以看到这个处理的基本步骤如下 执行Receive函数接收远程socket发送的信息 把信息从字节转换到string 处理该信息然后进入下一个循环继续等待socket发送新的信息。 值得注意的有几个 1Receive函数。这个函数和Listener的Accept函数类似。在这个地方等待执行如果没有新的消息这个函数就不会执行下一句一直等待。 2接收的是字节流需要转化成字符串 3判断远程关闭联接的方式 4如果对方的消息非常大还得循环接收这个data。 4如何管理这些联接thread 通过上边的程序基本上可以建立一个侦听并且处理联接会话。但是如何管理这些thread呢不然大量产生thread可是一个灾难。 管理的方法比较简单在Listener里面我定义了一个静态的哈希表(static public Hashtable Connectionsnew Hashtable();)存储Connection实例和它对应的Thread实例。而connection中也加入了一个最后联接时间的定义private DateTime _lastConnectTime;。在新链接建立的时候Listener的Accept()之后就把Connection实例和Thread实例存到哈希表中在Connection的Receive的时候修改最后联接时间。这样我们就可以知道该Connection在哪里并且会话是否活跃。 然后在Winform程序里头可以管理这些会话了设置设置超时。