zoukankan      html  css  js  c++  java
  • Socket编程 同步以及异步通信

    转自 https://www.cnblogs.com/BLoodMaster/archive/2010/07/02/1769774.html

    套接字简介:套接字最早是Unix的,window是借鉴过来的。TCP/IP协议族提供三种套接字:流式、数据报式、原始套接字。其中原始套接字允许对底层协议直接访问,一般用于检验新协议或者新设备问题,很少使用。

    套接字编程原理:延续文件作用思想,打开-读写-关闭的模式。

    C/S编程模式如下:

    • 服务器端:

    打开通信通道,告诉本地机器,愿意在该通道上接受客户请求——监听,等待客户请求——接受请求,创建专用链接进行读写——处理完毕,关闭专用链接——关闭通信通道(当然其中监听到关闭专用链接可以重复循环)

    • 客户端:打开通信通道,连接服务器——数据交互——关闭信道。

    Socket通信方式:

    • 同步:客户端在发送请求之后必须等到服务器回应之后才可以发送下一条请求。串行运行
    • 异步:客户端请求之后,不必等到服务器回应之后就可以发送下一条请求。并行运行

    套接字模式:

    • 阻塞:执行此套接字调用时,所有调用函数只有在得到返回结果之后才会返回。在调用结果返回之前,当前进程会被挂起。即此套接字一直被阻塞在网络调用上。
    • 非阻塞:执行此套接字调用时,调用函数即使得不到得到返回结果也会返回。

    套接字工作步骤:

    • 服务器监听:监听时服务器端套接字并不定位具体客户端套接字,而是处于等待链接的状态,实时监控网络状态
    • 客户端链接:客户端发出链接请求,要连接的目标是服务器端的套接字。为此客户端套接字必须描述服务器端套接字的服务器地址与端口号。
    • 链接确认:是指服务器端套接字监听到客户端套接字的链接请求时,它响应客户端链接请求,建立一个新的线程,把服务器端套接字的描述发送给客户端,一旦客户端确认此描述,则链接建立好。而服务器端的套接字继续处于监听状态,继续接受其他客户端套接字请求。

    在TCP/IP网络中,IP网络交互分类两大类:面向连接的交互与面向无连接的交互。

     

     

    Socket构造函数:public socket(AddressFamily 寻址类型, SocketType 套接字类型, ProtocolType 协议类型)。但需要注意的是套接字类型与协议类型并不是可以随便组合。

    SocketType

    ProtocolType

    描述

    Stream

    Tcp

    面向连接

    Dgram

    Udp

    面向无连接

    Raw

    Icmp

    网际消息控制

    Raw

    Raw

    基础传输协议

    Socket类的公共属性:

    属性名

    描述

    AddressFamily

    获取Socket的地址族

    Available

    获取已经从网络接收且可供读取的数据量

    Blocking

    获取或设置一个值,只是socket是否处于阻塞模式

    Connected

    获取一个值,指示当前连接状态

    Handle

    获取socket的操作系统句柄

    LocalEndPoint

    获取本地终端EndPoint

    RemoteEndPoint

    获取远程终端EndPoint

    ProtocolType

    获取协议类型

    SocketType

    获取SocketType类型

    Socket常用方法:

    Bind(EndPoint)

    服务器端套接字需要绑定到特定的终端,客户端也可以先绑定再请求连接

    Listen(int)

    监听端口,其中parameters表示最大监听数

    Accept()

    接受客户端链接,并返回一个新的链接,用于处理同客户端的通信问题

    Send()

    发送数据

    Send(byte[])

    简单发送数据

    Send(byte[],SocketFlag)

    使用指定的SocketFlag发送数据

    Send(byte[], int, SocketFlag)

    使用指定的SocketFlag发送指定长度数据

    Send(byte[], int, int, SocketFlag)

    使用指定的SocketFlag,将指定字节数的数据发送到已连接的socket(从指定偏移量开始)

    Receive()

    接受数据

    Receive(byte[])

    简单接受数据

    Receive (byte[],SocketFlag)

    使用指定的SocketFlag接受数据

    Receive (byte[], int, SocketFlag)

    使用指定的SocketFlag接受指定长度数据

    Receive (byte[], int, int, SocketFlag)

    使用指定的SocketFlag,从绑定的套接字接收指定字节数的数据,并存到指定偏移量位置的缓冲区

    Connect(EndPoint)

    连接远程服务器

    ShutDown(SocketShutDown)

    禁用套接字,其中SocketShutDown为枚举,Send禁止发送,Receive为禁止接受,Both为两者都禁止

    Close()

    关闭套接字,释放资源

    异步通信方法:

    BeginAccept(AsynscCallBack,object)

    开始一个一步操作接受一个连接尝试。参数:一个委托。一个对象。对象包含此请求的状态信息。其中回调方法中必须使用EndAccept方法。应用程序调用BegineAccept方法后,系统会使用单独的线程执行指定的回调方法并在EndAccept上一直处于阻塞状态,直至监测到挂起的链接。EndAccept会返回新的socket对象。供你来同远程主机数据交互。不能使用返回的这个socket接受队列中的任何附加连接。调用BeginAccept当希望原始线程阻塞的时候,请调用WaitHandle.WaitOne方法。当需要原始线程继续执行时请在回调方法中使用ManualResetEvent的set方法

    BeginConnect(EndPoint, AsyncCallBack, Object)

    回调方法中必须使用EndConnect()方法。Object中存储了连接的详细信息。

    BeginSend(byte[], SocketFlag, AsyncCallBack, Object)

    BegineReceive(byte[], SocketFlag, AsyncCallBack, Object)

    BegineDisconnect(bool, AsyncCallBack, Object)

                     

    给出同步通信与异步通信的示例:

    同步通信:

    预定义结构体,同步通信没有多线程异步委托回调,所以无需预定义结构体

    客户端Client:

     1 class Program
     2 
     3 {
     4 
     5         static void Main()
     6 
     7         {
     8 
     9             try{
    10 
    11                 int port = 2000;
    12 
    13                 string host = "127.0.0.1";
    14 
    15                 IPAddress ip = IPAddress.Parse(host);
    16 
    17                 IPEndPoint ipe = new IPEndPoint(ip, port);//把ip和端口转化为IPEndPoint实例
    18 
    19                 Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);//创建一个Socket
    20 
    21                 Console.WriteLine("Conneting...");
    22 
    23                 c.Connect(ipe);//连接到服务器
    24 
    25                 string sendStr = "hello!This is a socket test";
    26 
    27                 byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    28 
    29                 Console.WriteLine("Send Message");
    30 
    31                 c.Send(bs, bs.Length, 0);//发送测试信息
    32 
    33                 string recvStr = "";
    34 
    35                 byte[] recvBytes = new byte[1024];
    36 
    37                 int bytes;
    38 
    39                 bytes = c.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
    40 
    41                 recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    42 
    43                 Console.WriteLine("Client Get Message:{0}", recvStr);//显示服务器返回信息
    44 
    45                 c.Close();
    46 
    47             }
    48 
    49             catch (ArgumentNullException e){
    50 
    51                 Console.WriteLine("ArgumentNullException: {0}", e);
    52 
    53             }
    54 
    55             catch (SocketException e){
    56 
    57                 Console.WriteLine("SocketException: {0}", e);
    58 
    59             }
    60 
    61             Console.WriteLine("Press Enter to Exit");
    62 
    63             Console.ReadLine();
    64 
    65         }
    66 
    67 }
    View Code

    服务器端:

     1 class Program
     2 
     3 {
     4 
     5     static void Main()
     6 
     7     {
     8 
     9         try{
    10 
    11             int port = 2000;
    12 
    13             string host = "127.0.0.1";
    14 
    15             IPAddress ip = IPAddress.Parse(host);
    16 
    17             IPEndPoint ipe = new IPEndPoint(ip, port);
    18 
    19             Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);//创建一个Socket类
    20 
    21             s.Bind(ipe);//绑定2000端口
    22 
    23             s.Listen(0);//开始监听
    24 
    25             Console.WriteLine("Wait for connect");
    26 
    27             Socket temp = s.Accept();//为新建连接创建新的Socket。
    28 
    29             Console.WriteLine("Get a connect");
    30 
    31             string recvStr = "";
    32 
    33             byte[] recvBytes = new byte[1024];
    34 
    35             int bytes;
    36 
    37             bytes = temp.Receive(recvBytes, recvBytes.Length, 0);//从客户端接受信息
    38 
    39             recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    40 
    41             Console.WriteLine("Server Get Message:{0}", recvStr);//把客户端传来的信息显示出来
    42 
    43             string sendStr = "Ok!Client Send Message Sucessful!";
    44 
    45             byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    46 
    47             temp.Send(bs, bs.Length, 0);//返回客户端成功信息
    48 
    49             temp.Close();
    50 
    51             s.Close();
    52 
    53         }
    54 
    55         catch (ArgumentNullException e){
    56 
    57             Console.WriteLine("ArgumentNullException: {0}", e);}
    58 
    59         catch (SocketException e){
    60 
    61             Console.WriteLine("SocketException: {0}", e);}
    62 
    63         Console.WriteLine("Press Enter to Exit");
    64 
    65         Console.ReadLine();
    66 
    67     }
    68 
    69 }
    View Code

    异步通信:

    客户端Client:

    预定义结构体,用于异步委托之间的传递。用户根据自己需要定制即可

      1 public class StateObject
      2 
      3 {
      4 
      5     // Client socket.
      6 
      7     public Socket workSocket = null;
      8 
      9     // Size of receive buffer.
     10 
     11     public const int BufferSize = 256;
     12 
     13     // Receive buffer.
     14 
     15     public byte[] buffer = new byte[BufferSize];
     16 
     17     // Received data string.
     18 
     19     public StringBuilder sb = new StringBuilder();
     20 
     21 }
     22 
     23 正文:
     24 
     25 public class AsynchronousClient
     26 
     27 {
     28 
     29     // The port number for the remote device.
     30 
     31     private const int port = 11000;
     32 
     33     // ManualResetEvent instances signal completion.
     34 
     35     private static ManualResetEvent connectDone = new ManualResetEvent(false);
     36 
     37     private static ManualResetEvent sendDone = new ManualResetEvent(false);
     38 
     39     private static ManualResetEvent receiveDone = new ManualResetEvent(false);
     40 
     41     // The response from the remote device.
     42 
     43 private static String response = String.Empty;
     44 
     45  
     46 
     47     private static void StartClient(){
     48 
     49         // Connect to a remote device.
     50 
     51         try{
     52 
     53             // Establish the remote endpoint for the socket.
     54 
     55             // The name of the remote device is "host.contoso.com".
     56 
     57             IPHostEntry ipHostInfo = Dns.Resolve("host.contoso.com");
     58 
     59             IPAddress ipAddress = ipHostInfo.AddressList[0];
     60 
     61             IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
     62 
     63  
     64 
     65             // Create a TCP/IP socket.
     66 
     67             Socket client = new Socket(AddressFamily.InterNetwork,
     68 
     69                 SocketType.Stream, ProtocolType.Tcp);
     70 
     71  
     72 
     73             // Connect to the remote endpoint.
     74 
     75             client.BeginConnect(remoteEP,
     76 
     77                 new AsyncCallback(ConnectCallback), client);
     78 
     79             connectDone.WaitOne();
     80 
     81  
     82 
     83             // Send test data to the remote device.
     84 
     85             Send(client, "This is a test<EOF>");
     86 
     87             sendDone.WaitOne();
     88 
     89  
     90 
     91             // Receive the response from the remote device.
     92 
     93             Receive(client);
     94 
     95             receiveDone.WaitOne();
     96 
     97  
     98 
     99             // Write the response to the console.
    100 
    101             Console.WriteLine("Response received : {0}", response);
    102 
    103  
    104 
    105             // Release the socket.
    106 
    107             client.Shutdown(SocketShutdown.Both);
    108 
    109             client.Close();
    110 
    111 }
    112 
    113         catch (Exception e){
    114 
    115             Console.WriteLine(e.ToString());}
    116 
    117     }
    118 
    119  
    120 
    121     private static void ConnectCallback(IAsyncResult ar)
    122 
    123     {
    124 
    125         try{
    126 
    127             // Retrieve the socket from the state object.
    128 
    129             Socket client = (Socket)ar.AsyncState;
    130 
    131  
    132 
    133             // Complete the connection.
    134 
    135             client.EndConnect(ar);
    136 
    137  
    138 
    139             Console.WriteLine("Socket connected to {0}",
    140 
    141                 client.RemoteEndPoint.ToString());
    142 
    143  
    144 
    145             // Signal that the connection has been made.
    146 
    147             connectDone.Set();
    148 
    149         }
    150 
    151         catch (Exception e){
    152 
    153             Console.WriteLine(e.ToString());}
    154 
    155     }
    156 
    157  
    158 
    159     private static void Receive(Socket client)
    160 
    161     {
    162 
    163         try{
    164 
    165             // Create the state object.
    166 
    167             StateObject state = new StateObject();
    168 
    169             state.workSocket = client;
    170 
    171  
    172 
    173             // Begin receiving the data from the remote device.
    174 
    175             client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
    176 
    177                 new AsyncCallback(ReceiveCallback), state);
    178 
    179         }
    180 
    181         catch (Exception e){
    182 
    183             Console.WriteLine(e.ToString());}
    184 
    185     }
    186 
    187  
    188 
    189     private static void ReceiveCallback(IAsyncResult ar)
    190 
    191     {
    192 
    193         try{
    194 
    195             // Retrieve the state object and the client socket
    196 
    197             // from the asynchronous state object.
    198 
    199             StateObject state = (StateObject)ar.AsyncState;
    200 
    201             Socket client = state.workSocket;
    202 
    203  
    204 
    205             // Read data from the remote device.
    206 
    207             int bytesRead = client.EndReceive(ar);
    208 
    209  
    210 
    211             if (bytesRead > 0){
    212 
    213                 // There might be more data, so store the data received so far.
    214 
    215                 state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
    216 
    217  
    218 
    219                 // Get the rest of the data.
    220 
    221                 client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
    222 
    223                     new AsyncCallback(ReceiveCallback), state);
    224 
    225             }
    226 
    227             else{
    228 
    229                 // All the data has arrived; put it in response.
    230 
    231                 if (state.sb.Length > 1)
    232 
    233                 {
    234 
    235                     response = state.sb.ToString();
    236 
    237                 }
    238 
    239                 // Signal that all bytes have been received.
    240 
    241                 receiveDone.Set();
    242 
    243             }
    244 
    245         }
    246 
    247         catch (Exception e){
    248 
    249             Console.WriteLine(e.ToString());}
    250 
    251     }
    252 
    253  
    254 
    255     private static void Send(Socket client, String data)
    256 
    257     {
    258 
    259         // Convert the string data to byte data using ASCII encoding.
    260 
    261         byte[] byteData = Encoding.ASCII.GetBytes(data);
    262 
    263  
    264 
    265         // Begin sending the data to the remote device.
    266 
    267         client.BeginSend(byteData, 0, byteData.Length, 0,
    268 
    269             new AsyncCallback(SendCallback), client);
    270 
    271     }
    272 
    273  
    274 
    275     private static void SendCallback(IAsyncResult ar)
    276 
    277     {
    278 
    279         try{
    280 
    281             // Retrieve the socket from the state object.
    282 
    283             Socket client = (Socket)ar.AsyncState;
    284 
    285  
    286 
    287             // Complete sending the data to the remote device.
    288 
    289             int bytesSent = client.EndSend(ar);
    290 
    291             Console.WriteLine("Sent {0} bytes to server.", bytesSent);
    292 
    293  
    294 
    295             // Signal that all bytes have been sent.
    296 
    297             sendDone.Set();
    298 
    299 }
    300 
    301         catch (Exception e){
    302 
    303             Console.WriteLine(e.ToString());}
    304 
    305     }
    306 
    307  
    308 
    309     public static int Main(String[] args)
    310 
    311     {
    312 
    313         StartClient();
    314 
    315         return 0;
    316 
    317     }
    318 
    319 }
    View Code

    服务器端Server:预定义结构体,用于异步委托之间的传递。同客户端的一致。不再赘述

      1 // State object for reading client data asynchronously
      2 
      3 public class AsynchronousSocketListener
      4 
      5 {
      6 
      7     // Thread signal.
      8 
      9     public static ManualResetEvent allDone = new ManualResetEvent(false);
     10 
     11     public AsynchronousSocketListener(){}
     12 
     13     public static void StartListening()
     14 
     15     {
     16 
     17         // Data buffer for incoming data.
     18 
     19         byte[] bytes = new Byte[1024];
     20 
     21         // Establish the local endpoint for the socket.
     22 
     23         // The DNS name of the computer
     24 
     25         // running the listener is "host.contoso.com".
     26 
     27  
     28 
     29         //IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
     30 
     31         IPHostEntry ipHostInfo = Dns.Resolve("127.0.0.1");
     32 
     33         IPAddress ipAddress = ipHostInfo.AddressList[0];
     34 
     35         IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
     36 
     37         // Create a TCP/IP socket.
     38 
     39         Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
     40 
     41         // Bind the socket to the local endpoint and listen for incoming connections.
     42 
     43         try{
     44 
     45             listener.Bind(localEndPoint);
     46 
     47             listener.Listen(100);
     48 
     49             while (true){
     50 
     51                 // Set the event to nonsignaled state.
     52 
     53                 allDone.Reset();
     54 
     55                 // Start an asynchronous socket to listen for connections.
     56 
     57                 Console.WriteLine("Waiting for a connection...");
     58 
     59                 listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
     60 
     61                 // Wait until a connection is made before continuing.
     62 
     63                 allDone.WaitOne();
     64 
     65             }
     66 
     67         }
     68 
     69         catch (Exception e){
     70 
     71             Console.WriteLine(e.ToString());}
     72 
     73         Console.WriteLine("
    Press ENTER to continue...");
     74 
     75         Console.Read();
     76 
     77     }
     78 
     79     public static void AcceptCallback(IAsyncResult ar)
     80 
     81     {
     82 
     83         // Signal the main thread to continue.
     84 
     85         allDone.Set();
     86 
     87         // Get the socket that handles the client request.
     88 
     89         Socket listener = (Socket)ar.AsyncState;
     90 
     91         Socket handler = listener.EndAccept(ar);
     92 
     93         // Create the state object.
     94 
     95         StateObject state = new StateObject();
     96 
     97         state.workSocket = handler;
     98 
     99         handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,newAsyncCallback(ReadCallback), state);
    100 
    101     }
    102 
    103     public static void ReadCallback(IAsyncResult ar)
    104 
    105     {
    106 
    107         String content = String.Empty;
    108 
    109         // Retrieve the state object and the handler socket
    110 
    111         // from the asynchronous state object.
    112 
    113         StateObject state = (StateObject)ar.AsyncState;
    114 
    115         Socket handler = state.workSocket;
    116 
    117         // Read data from the client socket.
    118 
    119         int bytesRead = handler.EndReceive(ar);
    120 
    121         if (bytesRead > 0)
    122 
    123         {
    124 
    125             // There    might be more data, so store the data received so far.
    126 
    127             state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
    128 
    129             // Check for end-of-file tag. If it is not there, read
    130 
    131             // more data.
    132 
    133             content = state.sb.ToString();
    134 
    135             if (content.IndexOf("<EOF>") > -1){
    136 
    137                 // All the data has been read from the
    138 
    139                 // client. Display it on the console.
    140 
    141                 Console.WriteLine("Read {0} bytes from socket. 
     Data : {1}",
    142 
    143                 content.Length, content);
    144 
    145                 // Echo the data back to the client.
    146 
    147                 Send(handler, "Server return :" + content);
    148 
    149             }
    150 
    151             else{
    152 
    153                 // Not all data received. Get more.
    154 
    155                 handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
    156 
    157                 new AsyncCallback(ReadCallback), state);
    158 
    159             }
    160 
    161         }
    162 
    163     }
    164 
    165     private static void Send(Socket handler, String data){
    166 
    167         // Convert the string data to byte data using ASCII encoding.
    168 
    169         byte[] byteData = Encoding.ASCII.GetBytes(data);
    170 
    171         // Begin sending the data to the remote device.
    172 
    173         handler.BeginSend(byteData, 0, byteData.Length, 0,
    174 
    175         new AsyncCallback(SendCallback), handler);
    176 
    177     }
    178 
    179     private static void SendCallback(IAsyncResult ar)
    180 
    181     {
    182 
    183         try{
    184 
    185             // Retrieve the socket from the state object.
    186 
    187             Socket handler = (Socket)ar.AsyncState;
    188 
    189             // Complete sending the data to the remote device.
    190 
    191             int bytesSent = handler.EndSend(ar);
    192 
    193             Console.WriteLine("Sent {0} bytes to client.", bytesSent);
    194 
    195             handler.Shutdown(SocketShutdown.Both);
    196 
    197             handler.Close();
    198 
    199         }
    200 
    201         catch (Exception e){
    202 
    203             Console.WriteLine(e.ToString());
    204 
    205         }
    206 
    207     }
    208 
    209     public static int Main(String[] args)
    210 
    211     {
    212 
    213         StartListening();
    214 
    215         return 0;
    216 
    217     }
    218 
    219 }
    View Code
  • 相关阅读:
    js获取下拉框的值
    根据SNP的位置从基因组提取上下游序列
    PCA分析的疑问
    os删除文件或者文件夹
    python scipy包进行GO富集分析p值计算
    生物信息等级的划分
    docker笔记
    GATK4注意事项
    centos7修改yum源为阿里镜像
    idea如何通过数据库生成实体类
  • 原文地址:https://www.cnblogs.com/anyihen/p/12782109.html
Copyright © 2011-2022 走看看