zoukankan      html  css  js  c++  java
  • SOCKET原理(转载)

    SOCKET原理


    一、套接字(socket)概念


      套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

      应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应 用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

    二、建立socket连接


      建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。

      套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

    1. 服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求 
    2. 客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
    3. 连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户 端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

    三、SOCKET连接与TCP连接


      创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

    四、Socket连接与HTTP连接 

      由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用 中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。

      而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。

      很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送 给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可 以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。

    五、Socket服务端与客户端通信示意图

    六、服务端与客户端代码

      1、服务端

      (1)服务端窗口设计

      1 namespace SocketForm
      2 {
      3     partial class Form1
      4     {
      5         /// <summary>
      6         /// 必需的设计器变量。
      7         /// </summary>
      8         private System.ComponentModel.IContainer components = null;
      9 
     10         /// <summary>
     11         /// 清理所有正在使用的资源。
     12         /// </summary>
     13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
     14         protected override void Dispose(bool disposing)
     15         {
     16             if (disposing && (components != null))
     17             {
     18                 components.Dispose();
     19             }
     20             base.Dispose(disposing);
     21         }
     22 
     23         #region Windows 窗体设计器生成的代码
     24 
     25         /// <summary>
     26         /// 设计器支持所需的方法 - 不要
     27         /// 使用代码编辑器修改此方法的内容。
     28         /// </summary>
     29         private void InitializeComponent()
     30         {
     31             this.panel1 = new System.Windows.Forms.Panel();
     32             this.tb_ip = new System.Windows.Forms.TextBox();
     33             this.lb_Ip = new System.Windows.Forms.Label();
     34             this.lb_port = new System.Windows.Forms.Label();
     35             this.tb_port = new System.Windows.Forms.TextBox();
     36             this.bt_connnect = new System.Windows.Forms.Button();
     37             this.listBox1 = new System.Windows.Forms.ListBox();
     38             this.txt_msg = new System.Windows.Forms.TextBox();
     39             this.bt_send = new System.Windows.Forms.Button();
     40             this.panel1.SuspendLayout();
     41             this.SuspendLayout();
     42             // 
     43             // panel1
     44             // 
     45             this.panel1.Controls.Add(this.bt_connnect);
     46             this.panel1.Controls.Add(this.lb_port);
     47             this.panel1.Controls.Add(this.tb_port);
     48             this.panel1.Controls.Add(this.lb_Ip);
     49             this.panel1.Controls.Add(this.tb_ip);
     50             this.panel1.Location = new System.Drawing.Point(21, 12);
     51             this.panel1.Name = "panel1";
     52             this.panel1.Size = new System.Drawing.Size(580, 70);
     53             this.panel1.TabIndex = 0;
     54             // 
     55             // tb_ip
     56             // 
     57             this.tb_ip.Location = new System.Drawing.Point(44, 18);
     58             this.tb_ip.Name = "tb_ip";
     59             this.tb_ip.Size = new System.Drawing.Size(100, 21);
     60             this.tb_ip.TabIndex = 0;
     61             this.tb_ip.Text = "127.0.0.1";
     62             // 
     63             // lb_Ip
     64             // 
     65             this.lb_Ip.AutoSize = true;
     66             this.lb_Ip.Location = new System.Drawing.Point(15, 21);
     67             this.lb_Ip.Name = "lb_Ip";
     68             this.lb_Ip.Size = new System.Drawing.Size(23, 12);
     69             this.lb_Ip.TabIndex = 1;
     70             this.lb_Ip.Text = "IP:";
     71             // 
     72             // lb_port
     73             // 
     74             this.lb_port.AutoSize = true;
     75             this.lb_port.Location = new System.Drawing.Point(158, 24);
     76             this.lb_port.Name = "lb_port";
     77             this.lb_port.Size = new System.Drawing.Size(35, 12);
     78             this.lb_port.TabIndex = 3;
     79             this.lb_port.Text = "Port:";
     80             // 
     81             // tb_port
     82             // 
     83             this.tb_port.Location = new System.Drawing.Point(199, 21);
     84             this.tb_port.Name = "tb_port";
     85             this.tb_port.Size = new System.Drawing.Size(100, 21);
     86             this.tb_port.TabIndex = 2;
     87             this.tb_port.Text = "80";
     88             // 
     89             // bt_connnect
     90             // 
     91             this.bt_connnect.Location = new System.Drawing.Point(316, 15);
     92             this.bt_connnect.Name = "bt_connnect";
     93             this.bt_connnect.Size = new System.Drawing.Size(132, 42);
     94             this.bt_connnect.TabIndex = 4;
     95             this.bt_connnect.Text = "开始监听";
     96             this.bt_connnect.UseVisualStyleBackColor = true;
     97             this.bt_connnect.Click += new System.EventHandler(this.bt_connnect_Click);
     98             // 
     99             // listBox1
    100             // 
    101             this.listBox1.FormattingEnabled = true;
    102             this.listBox1.ItemHeight = 12;
    103             this.listBox1.Location = new System.Drawing.Point(21, 112);
    104             this.listBox1.Name = "listBox1";
    105             this.listBox1.Size = new System.Drawing.Size(580, 124);
    106             this.listBox1.TabIndex = 1;
    107             // 
    108             // txt_msg
    109             // 
    110             this.txt_msg.Location = new System.Drawing.Point(21, 255);
    111             this.txt_msg.Multiline = true;
    112             this.txt_msg.Name = "txt_msg";
    113             this.txt_msg.Size = new System.Drawing.Size(424, 73);
    114             this.txt_msg.TabIndex = 2;
    115             // 
    116             // bt_send
    117             // 
    118             this.bt_send.Location = new System.Drawing.Point(471, 266);
    119             this.bt_send.Name = "bt_send";
    120             this.bt_send.Size = new System.Drawing.Size(119, 52);
    121             this.bt_send.TabIndex = 3;
    122             this.bt_send.Text = "发送";
    123             this.bt_send.UseVisualStyleBackColor = true;
    124             this.bt_send.Click += new System.EventHandler(this.bt_send_Click);
    125             // 
    126             // Form1
    127             // 
    128             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
    129             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    130             this.ClientSize = new System.Drawing.Size(695, 340);
    131             this.Controls.Add(this.bt_send);
    132             this.Controls.Add(this.txt_msg);
    133             this.Controls.Add(this.listBox1);
    134             this.Controls.Add(this.panel1);
    135             this.Name = "Form1";
    136             this.Text = "SocketForm";
    137             this.Load += new System.EventHandler(this.Form1_Load);
    138             this.panel1.ResumeLayout(false);
    139             this.panel1.PerformLayout();
    140             this.ResumeLayout(false);
    141             this.PerformLayout();
    142 
    143         }
    144 
    145         #endregion
    146 
    147         private System.Windows.Forms.Panel panel1;
    148         private System.Windows.Forms.Button bt_connnect;
    149         private System.Windows.Forms.Label lb_port;
    150         private System.Windows.Forms.TextBox tb_port;
    151         private System.Windows.Forms.Label lb_Ip;
    152         private System.Windows.Forms.TextBox tb_ip;
    153         private System.Windows.Forms.ListBox listBox1;
    154         private System.Windows.Forms.TextBox txt_msg;
    155         private System.Windows.Forms.Button bt_send;
    156     }
    157 }
    View Code
     View Code

      (2)服务端逻辑设计

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.Linq;
      7 using System.Net;
      8 using System.Net.Sockets;
      9 using System.Text;
     10 using System.Threading;
     11 using System.Windows.Forms;
     12 
     13 namespace SocketForm
     14 {
     15     public partial class Form1 : Form
     16     {
     17         public Form1()
     18         {
     19             InitializeComponent();
     20         }
     21 
     22         private void bt_connnect_Click(object sender, EventArgs e)
     23         {
     24 
     25             try
     26             {
     27                 //点击开始监听时 在服务端创建一个负责监听IP和端口号的Socket
     28                 Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     29                 IPAddress ip = IPAddress.Any;
     30                 //创建对象端口
     31                 IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(tb_port.Text));
     32 
     33                 socketWatch.Bind(point);//绑定端口号
     34                 ShowMsg("监听成功!");
     35                 socketWatch.Listen(10);//设置监听
     36 
     37                 //创建监听线程
     38                 Thread thread = new Thread(Listen);
     39                 thread.IsBackground = true;
     40                 thread.Start(socketWatch);
     41             }
     42             catch { }
     43            
     44         }
     45        
     46         /// <summary>
     47         /// 等待客户端的连接 并且创建与之通信的Socket
     48         /// </summary>
     49         Socket socketSend;
     50         void Listen(object o)
     51         {
     52             try
     53             {
     54                 Socket socketWatch = o as Socket;
     55                 while (true)
     56                 {
     57                     socketSend = socketWatch.Accept();//等待接收客户端连接
     58                     ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + "连接成功!");
     59                     //开启一个新线程,执行接收消息方法
     60                     Thread r_thread = new Thread(Received);
     61                     r_thread.IsBackground = true;
     62                     r_thread.Start(socketSend);
     63                 }
     64             }
     65             catch { }
     66         }
     67         /// <summary>
     68         /// 服务器端不停的接收客户端发来的消息
     69         /// </summary>
     70         /// <param name="o"></param>
     71         void Received(object o)
     72         {
     73             try
     74             {
     75                 Socket socketSend = o as Socket;
     76                 while (true)
     77                 {
     78                     //客户端连接服务器成功后,服务器接收客户端发送的消息
     79                     byte[] buffer = new byte[1024 * 1024 * 3];
     80                     //实际接收到的有效字节数
     81                     int len = socketSend.Receive(buffer);
     82                     if (len == 0)
     83                     {
     84                         break;
     85                     }
     86                     string str = Encoding.UTF8.GetString(buffer, 0, len);
     87                     ShowMsg(socketSend.RemoteEndPoint + ":" + str);
     88                 }
     89             }
     90             catch { }
     91         }
     92         /// <summary>
     93         /// 服务器向客户端发送消息
     94         /// </summary>
     95         /// <param name="str"></param>
     96         void Send(string str) {
     97             byte[] buffer = Encoding.UTF8.GetBytes(str);
     98             socketSend.Send(buffer);
     99         }
    100 
    101         void ShowMsg(string msg)
    102         {
    103             listBox1.Items.Add(msg + "
    ");
    104         }
    105 
    106         private void Form1_Load(object sender, EventArgs e)
    107         {
    108             Control.CheckForIllegalCrossThreadCalls = false;
    109         }
    110 
    111         private void bt_send_Click(object sender, EventArgs e)
    112         {
    113             Send(txt_msg.Text.Trim());
    114         }
    115     }
    116 }
    View Code
     View Code

      2、客户端

      (1)客户端窗口设计

      1 namespace SocketClient
      2 {
      3     partial class Form1
      4     {
      5         /// <summary>
      6         /// 必需的设计器变量。
      7         /// </summary>
      8         private System.ComponentModel.IContainer components = null;
      9 
     10         /// <summary>
     11         /// 清理所有正在使用的资源。
     12         /// </summary>
     13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
     14         protected override void Dispose(bool disposing)
     15         {
     16             if (disposing && (components != null))
     17             {
     18                 components.Dispose();
     19             }
     20             base.Dispose(disposing);
     21         }
     22 
     23         #region Windows 窗体设计器生成的代码
     24 
     25         /// <summary>
     26         /// 设计器支持所需的方法 - 不要
     27         /// 使用代码编辑器修改此方法的内容。
     28         /// </summary>
     29         private void InitializeComponent()
     30         {
     31             this.panel1 = new System.Windows.Forms.Panel();
     32             this.lb_ip = new System.Windows.Forms.Label();
     33             this.txt_ip = new System.Windows.Forms.TextBox();
     34             this.txt_port = new System.Windows.Forms.TextBox();
     35             this.lb_port = new System.Windows.Forms.Label();
     36             this.bt_connect = new System.Windows.Forms.Button();
     37             this.textBox1 = new System.Windows.Forms.TextBox();
     38             this.txt_msg = new System.Windows.Forms.TextBox();
     39             this.bt_send = new System.Windows.Forms.Button();
     40             this.panel1.SuspendLayout();
     41             this.SuspendLayout();
     42             // 
     43             // panel1
     44             // 
     45             this.panel1.Controls.Add(this.bt_connect);
     46             this.panel1.Controls.Add(this.txt_port);
     47             this.panel1.Controls.Add(this.lb_port);
     48             this.panel1.Controls.Add(this.txt_ip);
     49             this.panel1.Controls.Add(this.lb_ip);
     50             this.panel1.Location = new System.Drawing.Point(12, 12);
     51             this.panel1.Name = "panel1";
     52             this.panel1.Size = new System.Drawing.Size(463, 75);
     53             this.panel1.TabIndex = 0;
     54             // 
     55             // lb_ip
     56             // 
     57             this.lb_ip.AutoSize = true;
     58             this.lb_ip.Location = new System.Drawing.Point(14, 23);
     59             this.lb_ip.Name = "lb_ip";
     60             this.lb_ip.Size = new System.Drawing.Size(23, 12);
     61             this.lb_ip.TabIndex = 0;
     62             this.lb_ip.Text = "IP:";
     63             // 
     64             // txt_ip
     65             // 
     66             this.txt_ip.Location = new System.Drawing.Point(43, 20);
     67             this.txt_ip.Name = "txt_ip";
     68             this.txt_ip.Size = new System.Drawing.Size(100, 21);
     69             this.txt_ip.TabIndex = 1;
     70             this.txt_ip.Text = "127.0.0.1";
     71             // 
     72             // txt_port
     73             // 
     74             this.txt_port.Location = new System.Drawing.Point(207, 23);
     75             this.txt_port.Name = "txt_port";
     76             this.txt_port.Size = new System.Drawing.Size(100, 21);
     77             this.txt_port.TabIndex = 3;
     78             this.txt_port.Text = "2001";
     79             // 
     80             // lb_port
     81             // 
     82             this.lb_port.AutoSize = true;
     83             this.lb_port.Location = new System.Drawing.Point(166, 29);
     84             this.lb_port.Name = "lb_port";
     85             this.lb_port.Size = new System.Drawing.Size(35, 12);
     86             this.lb_port.TabIndex = 2;
     87             this.lb_port.Text = "port:";
     88             // 
     89             // bt_connect
     90             // 
     91             this.bt_connect.Location = new System.Drawing.Point(313, 9);
     92             this.bt_connect.Name = "bt_connect";
     93             this.bt_connect.Size = new System.Drawing.Size(113, 47);
     94             this.bt_connect.TabIndex = 4;
     95             this.bt_connect.Text = "连接";
     96             this.bt_connect.UseVisualStyleBackColor = true;
     97             this.bt_connect.Click += new System.EventHandler(this.bt_connect_Click);
     98             // 
     99             // textBox1
    100             // 
    101             this.textBox1.Location = new System.Drawing.Point(12, 103);
    102             this.textBox1.Multiline = true;
    103             this.textBox1.Name = "textBox1";
    104             this.textBox1.Size = new System.Drawing.Size(463, 114);
    105             this.textBox1.TabIndex = 1;
    106             // 
    107             // txt_msg
    108             // 
    109             this.txt_msg.Location = new System.Drawing.Point(12, 246);
    110             this.txt_msg.Multiline = true;
    111             this.txt_msg.Name = "txt_msg";
    112             this.txt_msg.Size = new System.Drawing.Size(291, 54);
    113             this.txt_msg.TabIndex = 2;
    114             // 
    115             // bt_send
    116             // 
    117             this.bt_send.Location = new System.Drawing.Point(325, 246);
    118             this.bt_send.Name = "bt_send";
    119             this.bt_send.Size = new System.Drawing.Size(113, 54);
    120             this.bt_send.TabIndex = 3;
    121             this.bt_send.Text = "发送";
    122             this.bt_send.UseVisualStyleBackColor = true;
    123             this.bt_send.Click += new System.EventHandler(this.bt_send_Click);
    124             // 
    125             // Form1
    126             // 
    127             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
    128             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    129             this.ClientSize = new System.Drawing.Size(493, 323);
    130             this.Controls.Add(this.bt_send);
    131             this.Controls.Add(this.txt_msg);
    132             this.Controls.Add(this.textBox1);
    133             this.Controls.Add(this.panel1);
    134             this.Name = "Form1";
    135             this.Text = "Form1";
    136             this.Load += new System.EventHandler(this.Form1_Load);
    137             this.panel1.ResumeLayout(false);
    138             this.panel1.PerformLayout();
    139             this.ResumeLayout(false);
    140             this.PerformLayout();
    141 
    142         }
    143 
    144         #endregion
    145 
    146         private System.Windows.Forms.Panel panel1;
    147         private System.Windows.Forms.Label lb_ip;
    148         private System.Windows.Forms.Button bt_connect;
    149         private System.Windows.Forms.TextBox txt_port;
    150         private System.Windows.Forms.Label lb_port;
    151         private System.Windows.Forms.TextBox txt_ip;
    152         private System.Windows.Forms.TextBox textBox1;
    153         private System.Windows.Forms.TextBox txt_msg;
    154         private System.Windows.Forms.Button bt_send;
    155     }
    156 }
     View Code

      (2)客户端逻辑设计

     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Data;
     5 using System.Drawing;
     6 using System.Linq;
     7 using System.Net;
     8 using System.Net.Sockets;
     9 using System.Text;
    10 using System.Threading;
    11 using System.Windows.Forms;
    12 
    13 namespace SocketClient
    14 {
    15     public partial class Form1 : Form
    16     {
    17         public Form1()
    18         {
    19             InitializeComponent();
    20         }
    21         Socket socketSend;
    22         private void bt_connect_Click(object sender, EventArgs e)
    23         {
    24             try
    25             {
    26                 //创建客户端Socket,获得远程ip和端口号
    27                 socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    28                 IPAddress ip = IPAddress.Parse(txt_ip.Text);
    29                 IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txt_port.Text));
    30 
    31                 socketSend.Connect(point);
    32                 ShowMsg("连接成功!");
    33                 //开启新的线程,不停的接收服务器发来的消息
    34                 Thread c_thread = new Thread(Received);
    35                 c_thread.IsBackground = true;
    36                 c_thread.Start();
    37             }
    38             catch (Exception){
    39                 ShowMsg("IP或者端口号错误...");
    40             }
    41  
    42         }
    43         void ShowMsg(string str)
    44         {
    45             textBox1.AppendText(str + "
    ");
    46         }
    47         /// <summary>
    48         /// 接收服务端返回的消息
    49         /// </summary>
    50         void Received()
    51         {
    52             while (true)
    53             {
    54                 try
    55                 {
    56                     byte[] buffer = new byte[1024 * 1024 * 3];
    57                     //实际接收到的有效字节数
    58                     int len = socketSend.Receive(buffer);
    59                     if (len == 0)
    60                     {
    61                         break;
    62                     }
    63                     string str = Encoding.UTF8.GetString(buffer, 0, len);
    64                     ShowMsg(socketSend.RemoteEndPoint + ":" + str);
    65                 }
    66                 catch { }
    67             }
    68         } 
    69         /// <summary>
    70         /// 向服务器发送消息
    71         /// </summary>
    72         /// <param name="sender"></param>
    73         /// <param name="e"></param>
    74         private void bt_send_Click(object sender, EventArgs e)
    75         {
    76             try
    77             {
    78                 string msg = txt_msg.Text.Trim();
    79                 byte[] buffer = new byte[1024 * 1024 * 3];
    80                 buffer = Encoding.UTF8.GetBytes(msg);
    81                 socketSend.Send(buffer);
    82             }
    83             catch { }
    84         }
    85 
    86         private void Form1_Load(object sender, EventArgs e)
    87         {
    88             Control.CheckForIllegalCrossThreadCalls = false;
    89         }
    90     }
    91 }
     View Code

    七、运行效果

      1、服务端

      2、客户端

  • 相关阅读:
    dstat
    centos安装指定版本的golang
    APP防CC为什么复杂
    火狐浏览器的书签如何自动在新窗口打开?
    linux jdk版本随时切换
    centos7 yum安装java环境
    kangle清除缓存接口
    CC攻击原理及防范方法
    GET 和 POST 的区别 以及为什么 GET请求 比 POST请求 更快
    HTTP缓存机制
  • 原文地址:https://www.cnblogs.com/mamiyiya777/p/6651185.html
Copyright © 2011-2022 走看看