socket简单的访问流程

最近看了一些关于socket的东西,感觉蛮好用的,现把socket的简单通讯步骤记起来,以便学习:

1、新建Socket        

  Socket  s = new Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType)。

  如:Socket s = new Soc ket(AddressFamily.InterNetw ork, SocketType.Stream, ProtocolType.Tcp);

  //当然还可以是其他协议类型,如udp  

  Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

  注:stream socket是面向连接的,打开之后的通讯过程必须始终保持连接。数据传输是可靠的,假如发送方发送“1,2”两个包,则接收方也会以相同的顺序接  接收到两个包,且保证数据的正确性,它是基于tcp协议传输的。dgram socket是非面向连接,如果发送方发送一个包,不需要事先建立连接,发送方的数据不能保证收到,即使收到了也不能保证以相同的顺序收到,但是能保证每个包数据的完整性,就像一封电报,它通过udp协议完成。

 

2、通过 Connect 方法连接到指定的服务器。

    有Connect就肯定要有东西让它去connect啦,这就是IPEndPoint。IPEndPoint  类包含应用程序连接到主机上的服务所需的主机和端口信息,通过组合服务的主机 IP 地址和端口号,IPEndPoint  类形成连接到服务的连接点。 (在 Internet 中,TCP/IP  使用 一个网络地址和一个服务端口号来唯一标识设备)

  如:IPEndPoint ipe = new IPEndPoint(IPAddress address, int port);

  如何获取IPAddress呢?.net有两种类来处理:

  (1)IPAddress 类:IPAddress  类包含计算机在 IP  网络上的地址。其 Parse 方法可将 IP地址字符串转换为 IPAddress  实例。下面的语句创建一IPAddress  实例:IPAddress myIP = IPAddress.Parse("192.168.1.2");

  (2)Dns 类:向使用 TCP/IP Internet  服务的应用程序提供域名服务。其 Resolve  方法查询 DNS  服务器以将用户友好的域名(如www.cnblogs.com)映射到数字形式的 Internet  地址(61.155.169.116)。Resolve 方法 返回一个 IPHostEnty  实例,该实例包含所请求名称的地址和别名的列表。大多数情况下,可以使用 AddressList 数组中返回的第一个地址。下面的代码获取一个  IPAddress  实例,该实例包含服务器 www.cnblogs.com  的 IP  地址。

    如:IPHostEntry ihe = Dns.Resolve("www.cnblogs.com");

      IPAddress iar = ihe.AddressList[0];

      也可以使用 GetHostName 方法得到 IPHostEntry 实例:

       IPHosntEntry ihe=Dns.GetHostByName("www.cnblogs.com")

  知道了上面的知识后,我们很容易就知道怎么连接服务器了吧:

  IPAddress myIP = IPAddress.Parse("192.168.1.2");

  IPEndPoint ipep = new IPEndPoint(myIP,8888);

      try
      {
            s.Connect(ipep);
      }

      catch (SocketException ex)
            {
                MessageBox.Show("connect error: " + ex.Message);
                return;
            }

   //如果在执行Socket连接时,服务器的Socket侦听没有开启的话,会产生一个SocketException异常,如果没有异常发生,那恭喜你,你已经与服务器连接上了,接下来就可以跟服务器通信了。

 

3、成功连接后我们就可以通讯啦!!通过 Send/SendTo 方法向远程服务器发送数据,而后可以通过 Receive/ReceiveFrom 从服务端接收数据。

Send :      public int Send(byte[] buffer);   //直接把要发送的数据转换为System.Byte 类型的数组发送,返回已发送到连接的Socket 的字节数

      public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags); //offset发送的开始位置,size: 要发送的字节数,SocketFlags

      指定套接字接收和发送的行为;

      ......

Receive:     public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags);  //buffer存储所接收数据的位置,所以在Receive前要先初始化                         byte[], offset:buffer存储的位置,size:接收的字节数
           ......

      通常接收方都必须绑定本机的终结点,然后侦听

        IPEndPoint ipep = new IPEndPoint(IPAddress.Any, int.Parse("8888")); //IPAddress.Any指定所有网络接口上的客户端活动

              //创建一个套接字
              Socket rec = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

              //绑定套接字到指定端口
              rec.Bind(ipep);

              rec.Listen(10);  //10是挂起连接队列的最大长度。

      while (true)
                {

        Socket s = rec.Accept();

        string SendFileName = System.Text.Encoding.Unicode.GetString(Module.ReceiveVarData(s));

        //接收完后记得关闭Socket

        s.Close();

        ......

      }
      进入while循环,等待新的联接;如果有新的联接,那么建立新的socket来对应这个联接的会话。值得注意的就是这一句联接代码:rec.Accept()。执行这一句的时候,程序就在这个地方等待,直到有新的联检请求的时候程序才会执行下一句。这是同步执行,当然也可以异步执行。


 

下面两个是常用的socket发送接收函数:

View Code
//发送函数
public static int SendVarData(Socket s, byte[] data)
{
int total = 0;
int size = data.Length;
int dataleft = size;
int sent;
byte[] datasize = new byte[4];
datasize
= BitConverter.GetBytes(size);
sent
= s.Send(datasize);

while (total < size)
{
sent
= s.Send(data, total, dataleft, SocketFlags.None);
total
+= sent;
dataleft
-= sent;
}

return total;
}

//接收函数
public static byte[] ReceiveVarData(Socket s)
{
int total = 0;
int recv;
byte[] datasize = new byte[4];
recv
= s.Receive(datasize, 0, 4, SocketFlags.None);
int size = BitConverter.ToInt32(datasize, 0);
int dataleft = size;
byte[] data = new byte[size];
while (total < size)
{
recv
= s.Receive(data, total, dataleft, SocketFlags.None);
if (recv == 0)
{
data
= null;
break;
}
total
+= recv;
dataleft
-= recv;
}
return data;
}

posted on 2011-07-02 10:53  congplayer  阅读(3982)  评论(6编辑  收藏  举报

导航