要想理解socket,就得先熟悉TCP/IP协议族,TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何再它们之间传输的标准。

  从字面意思来看TCP/IP是TCP和IP协议的合称,但实际上TCP/IP协议是指因特网整个TCP/IP协议族。不同于ISO模型的七个分层,TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中。

  应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等

  传输层:TCP,UDP

  网络层:IP,ICMP,OSPF,EIGRP,IGMP

  数据链路层:SLIP,CSLIP,PPP,MTU

  每一抽象层建立在低一层提供的服务上,并且为高一层提供服务,如下图所示:

      

      

  那我们要找的socket在哪里呢?

        

  Socket

  我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。

  Socket通信流程:

        

  在此,Socket可以像流Stream一样视为一个数据通道,这个通道假设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。在应用程序段或者服务器端创建了Socket对象之后,就可以使用Send/SentTo方法将数据发送到连接的Socket上,或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据。

  在使用Socket之前,首先要创建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。其间用到的方法/函数有:

  Scoket.Connect();建立到远程设备的连接;

  public void Connect(EndPoint remoteEP)(有重载方法)

  Socket.Send();从数据中的指示位置开始讲数据发送到连接的Socket;

  public int Send(byte[],EndPoint);(有重载方法)

  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与一个bending终结点相关联;

  public void Bind(EndPoint LoaclEP);

  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类形成到服务的连接点。

  用到EndPoint类的时候就不可避免的设计到计算机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 hostInfo=Dns.GetHostByName("host.contoso.com")

  在使用以上方法时,你将可能需要处理以下几种异常:

  • SocketException异常:访问Socket时操作系统发生错误引发
  • ArgumentNullException异常:参数为空引用引发
  • ObjectDisposedException异常:Socket已经关闭引发

  在掌握上面得知识后,下面的代码将该服务器主机( host.contoso.com的 IP 地址与端口号组合,以便为连接创建远程终结点:

   IPEndPoint ipe = new IPEndPoint(ipAddress,);

  确定了远程设备的地址并选择了用于连接的端口后,应用程序可以尝试建立与远程设备的连接。下面的示例使用现有的 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.1rnHost: " + server + "rnConnection: Closernrn";

  远程主机指定端口接受到这一请求后,就可利用其公用服务程序进行处理而不需要另行编制服务器端应用程序。

  综合运用以上阐述的使用Visual C#进行Socket网络程序开发的知识,下面的程序段完整地实现了Web页面下载功能。用户只需在窗体上输入远程主机名(Dns 主机名或以点分隔的四部分表示法格式的 IP 地址)和预保存的本地文件名,并利用专门提供Http服务的80端口,就可以获取远程主机页面并保存在本地机指定文件中。如果保存格式是.htm格式,你就可以在Internet浏览器中打开该页面。适当添加代码,你甚至可以实现一个简单的浏览器程序。

  实现此功能的主要源代码如下:

 //"开始"按钮事件
private void button1_Click(object sender, System.EventArgs e) {
//取得预保存的文件名
string fileName=textBox3.Text.Trim();
//远程主机
string hostName=textBox1.Text.Trim();
//端口
int port=Int32.Parse(textBox2.Text.Trim());
//得到主机信息
IPHostEntry ipInfo=Dns.GetHostByName(hostName);
//取得IPAddress[]
IPAddress[] ipAddr=ipInfo.AddressList;
//得到ip
IPAddress ip=ipAddr[];
//组合出远程终结点
IPEndPoint hostEP=new IPEndPoint(ip,port);
//创建Socket 实例
Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
try
{
//尝试连接
socket.Connect(hostEP);
}
catch(Exception se)
{
MessageBox.Show("连接错误"+se.Message,"提示信息
,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
}
//发送给远程主机的请求内容串
string sendStr="GET / HTTP/1.1rnHost: " + hostName +
"rnConnection: Closernrn";
//创建bytes字节数组以转换发送串
byte[] bytesSendStr=new byte[];
//将发送内容字符串转换成字节byte数组
bytesSendStr=Encoding.ASCII.GetBytes(sendStr);
try
{
//向主机发送请求
socket.Send(bytesSendStr,bytesSendStr.Length,);
}
catch(Exception ce)
{
MessageBox.Show("发送错误:"+ce.Message,"提示信息
,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
}
//声明接收返回内容的字符串
string recvStr="";
//声明字节数组,一次接收数据的长度为1024字节
byte[] recvBytes=new byte[];
//返回实际接收内容的字节数
int bytes=;
//循环读取,直到接收完所有数据
while(true)
{
bytes=socket.Receive(recvBytes,recvBytes.Length,);
//读取完成后退出循环
if(bytes〈=)
break;
//将读取的字节数转换为字符串
recvStr+=Encoding.ASCII.GetString(recvBytes,,bytes);
}
//将所读取的字符串转换为字节数组
byte[] content=Encoding.ASCII.GetBytes(recvStr);
try
{
//创建文件流对象实例
FileStream fs=new FileStream(fileName,FileMode.OpenOrCreate,FileAccess.ReadWrite);
//写入文件
fs.Write(content,,content.Length);
}
catch(Exception fe)
{
MessageBox.Show("文件创建/写入错误:"+fe.Message,"提示信息",MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
}
//禁用Socket
socket.Shutdown(SocketShutdown.Both);
//关闭Socket
socket.Close();
}
}

参考:http://blog.sina.com.cn/s/blog_7315615d0101wvom.html

   http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx

   http://www.cnblogs.com/dolphinX/p/3460545.html

对socket的理解的更多相关文章

  1. linux中socket的理解

    对linux中socket的理解 一.socket 一般来说socket有一个别名也叫做套接字. socket起源于Unix,都可以用“打开open –> 读写write/read –> ...

  2. Socket 的理解及实例

    Socket 的理解及实例Socket 的理解TCP/IP要想理解socket首先得熟悉一下TCP/IP协议族, TCP/IP(Transmission Control Protocol/Intern ...

  3. php socket 简单理解

    以下内容转自:https://www.cnblogs.com/loveyoume/p/6076101.html 和 https://www.cnblogs.com/WuNaiHuaLuo/p/6107 ...

  4. python socket 的理解(1)

    前言 socket的用法简单,但里面的概念有点模糊,记录自己本人的一点理解. socket层结构图 注意,从此图中看出socket处于tcp和应用层之间.那么它代表啥意思呢?简明的说,数据的传输都是底 ...

  5. linux中socket的理解---4

    一.socket 一般来说socket有一个别名也叫做套接字. socket起源于Unix,都可以用“打 开open –> 读写write/read –> 关闭close”模式来操作.So ...

  6. socket keepalive理解

    java socket编程中有个keepalive选项,看到这个选项经常会误解为长连接,不设置则为短连接,实则不然. socket连接建立之后,只要双方均未主动关闭连接,那这个连接就是会一直保持的,就 ...

  7. 对Swoole、Workerman和php自带的socket的理解

    为什么php自带的socket不怎么听说,基本都是用swoole,workerman去实现? 1.PHP的socket扩展是一套socket api,仅此而已. swoole,用C实现,它的socke ...

  8. TCP/IP Socket 的理解

         网络由下往上分为:物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.      TCP 协议对应于传输层,HTTP 协议对应应用层,Socket 则是对 TCP/IP 协议的封装. ...

  9. TCP/IP、Http、Socket 简单理解

    转自:http://blog.csdn.net/guyan0319 https://blog.csdn.net/guyan0319/article/details/79404216 一. 什么是TCP ...

随机推荐

  1. Ubuntu 16.04安装GTX960闭源驱动

    GTX960的闭源要Nvidia 346版才行,闭源驱动能很大提升显卡的性能,例如双显示输出等,缺点是不开源. 有以下方式来安装: 1.命令行: sudo add-apt-repository -y ...

  2. 实战!利用MSF批量扫描校园网中含有MS17_010漏洞的主机并入侵

    利用ms17_010的永恒之蓝在前些日子火爆了一段时间,校园网中也声称封锁了相应端口.最近在搞MSF的深入学习,于是有了下文. ms17_010扫描工具 msf中的辅助模块含有一个强大的ms17_01 ...

  3. C++ - 库函数优先级队列(priority_queue)输出最小值 代码

    库函数优先级队列(priority_queue)输出最小值 代码 本文地址: http://blog.csdn.net/caroline_wendy 库函数优先级队列(priority_queue)的 ...

  4. dumpdecrypted进行砸壳

    1.下载源码git clone git://github.com/stefanesser/dumpdecrypted/ 2.进行编译生成 dumpdecrypted.dylibmake 3.将dump ...

  5. win32gui.EnumWindows my.os.EnumWindows.py

    import win32guidef _MyCallback(hwnd, extra): windows = extra temp = [] temp.append(hex(hwnd)) temp.a ...

  6. 记一次ORA-600[13011]

    SunOS 5.10 Oracle 10.2.0.2.0 开发环境某一数据库出现ora-600报错. alert.log中的报错信息: Thu Nov 13 15:11:43 2014 Errors ...

  7. ASP.NET调用存储过程并接收存储过程返回值

    ASP.NET调用存储过程并接收存储过程返回值 2010-08-02 11:26:17|  分类: C#|字号 订阅       2010年02月27日 星期六 23:52 假设表结构Create T ...

  8. 【Silverlight】Bing Maps学习系列(三):如何控制地图

    [Silverlight]Bing Maps学习系列(三):如何控制地图 本篇主要介绍如何对地图的一些常用控制操作,包括地图加载模式.根据精度和纬度定位.变焦程度等. 一.动态设置地图加载模式 在本系 ...

  9. android EditText如何使光标随着输入内容移动

    EditText 使光标随着输入内容移动的setSelection()

  10. 排名Top 100的Java类库

    和去年一样,排名第一的类库,依旧是JUnit.基于它扩展的 JUnit Runner 占据第二名的位置,甚至是较旧的 junit.framework 此次也在第三名的位置.也就是说JUnit包揽了前三 ...