zoukankan      html  css  js  c++  java
  • Socket通信实例(C#)


      套接字(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)服务端窗口设计

    namespace SocketForm
    {
        partial class Form1
        {
            /// <summary>
            /// 必需的设计器变量。
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary>
            /// 清理所有正在使用的资源。
            /// </summary>
            /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region Windows 窗体设计器生成的代码
    
            /// <summary>
            /// 设计器支持所需的方法 - 不要
            /// 使用代码编辑器修改此方法的内容。
            /// </summary>
            private void InitializeComponent()
            {
                this.panel1 = new System.Windows.Forms.Panel();
                this.tb_ip = new System.Windows.Forms.TextBox();
                this.lb_Ip = new System.Windows.Forms.Label();
                this.lb_port = new System.Windows.Forms.Label();
                this.tb_port = new System.Windows.Forms.TextBox();
                this.bt_connnect = new System.Windows.Forms.Button();
                this.listBox1 = new System.Windows.Forms.ListBox();
                this.txt_msg = new System.Windows.Forms.TextBox();
                this.bt_send = new System.Windows.Forms.Button();
                this.panel1.SuspendLayout();
                this.SuspendLayout();
                // 
                // panel1
                // 
                this.panel1.Controls.Add(this.bt_connnect);
                this.panel1.Controls.Add(this.lb_port);
                this.panel1.Controls.Add(this.tb_port);
                this.panel1.Controls.Add(this.lb_Ip);
                this.panel1.Controls.Add(this.tb_ip);
                this.panel1.Location = new System.Drawing.Point(21, 12);
                this.panel1.Name = "panel1";
                this.panel1.Size = new System.Drawing.Size(580, 70);
                this.panel1.TabIndex = 0;
                // 
                // tb_ip
                // 
                this.tb_ip.Location = new System.Drawing.Point(44, 18);
                this.tb_ip.Name = "tb_ip";
                this.tb_ip.Size = new System.Drawing.Size(100, 21);
                this.tb_ip.TabIndex = 0;
                this.tb_ip.Text = "127.0.0.1";
                // 
                // lb_Ip
                // 
                this.lb_Ip.AutoSize = true;
                this.lb_Ip.Location = new System.Drawing.Point(15, 21);
                this.lb_Ip.Name = "lb_Ip";
                this.lb_Ip.Size = new System.Drawing.Size(23, 12);
                this.lb_Ip.TabIndex = 1;
                this.lb_Ip.Text = "IP:";
                // 
                // lb_port
                // 
                this.lb_port.AutoSize = true;
                this.lb_port.Location = new System.Drawing.Point(158, 24);
                this.lb_port.Name = "lb_port";
                this.lb_port.Size = new System.Drawing.Size(35, 12);
                this.lb_port.TabIndex = 3;
                this.lb_port.Text = "Port:";
                // 
                // tb_port
                // 
                this.tb_port.Location = new System.Drawing.Point(199, 21);
                this.tb_port.Name = "tb_port";
                this.tb_port.Size = new System.Drawing.Size(100, 21);
                this.tb_port.TabIndex = 2;
                this.tb_port.Text = "80";
                // 
                // bt_connnect
                // 
                this.bt_connnect.Location = new System.Drawing.Point(316, 15);
                this.bt_connnect.Name = "bt_connnect";
                this.bt_connnect.Size = new System.Drawing.Size(132, 42);
                this.bt_connnect.TabIndex = 4;
                this.bt_connnect.Text = "开始监听";
                this.bt_connnect.UseVisualStyleBackColor = true;
                this.bt_connnect.Click += new System.EventHandler(this.bt_connnect_Click);
                // 
                // listBox1
                // 
                this.listBox1.FormattingEnabled = true;
                this.listBox1.ItemHeight = 12;
                this.listBox1.Location = new System.Drawing.Point(21, 112);
                this.listBox1.Name = "listBox1";
                this.listBox1.Size = new System.Drawing.Size(580, 124);
                this.listBox1.TabIndex = 1;
                // 
                // txt_msg
                // 
                this.txt_msg.Location = new System.Drawing.Point(21, 255);
                this.txt_msg.Multiline = true;
                this.txt_msg.Name = "txt_msg";
                this.txt_msg.Size = new System.Drawing.Size(424, 73);
                this.txt_msg.TabIndex = 2;
                // 
                // bt_send
                // 
                this.bt_send.Location = new System.Drawing.Point(471, 266);
                this.bt_send.Name = "bt_send";
                this.bt_send.Size = new System.Drawing.Size(119, 52);
                this.bt_send.TabIndex = 3;
                this.bt_send.Text = "发送";
                this.bt_send.UseVisualStyleBackColor = true;
                this.bt_send.Click += new System.EventHandler(this.bt_send_Click);
                // 
                // Form1
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(695, 340);
                this.Controls.Add(this.bt_send);
                this.Controls.Add(this.txt_msg);
                this.Controls.Add(this.listBox1);
                this.Controls.Add(this.panel1);
                this.Name = "Form1";
                this.Text = "SocketForm";
                this.Load += new System.EventHandler(this.Form1_Load);
                this.panel1.ResumeLayout(false);
                this.panel1.PerformLayout();
                this.ResumeLayout(false);
                this.PerformLayout();
    
            }
    
            #endregion
    
            private System.Windows.Forms.Panel panel1;
            private System.Windows.Forms.Button bt_connnect;
            private System.Windows.Forms.Label lb_port;
            private System.Windows.Forms.TextBox tb_port;
            private System.Windows.Forms.Label lb_Ip;
            private System.Windows.Forms.TextBox tb_ip;
            private System.Windows.Forms.ListBox listBox1;
            private System.Windows.Forms.TextBox txt_msg;
            private System.Windows.Forms.Button bt_send;
        }
    }
    View Code

           (2)服务端逻辑设计

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace SocketForm
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void bt_connnect_Click(object sender, EventArgs e)
            {
    
                try
                {
                    //点击开始监听时 在服务端创建一个负责监听IP和端口号的Socket
                    Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    IPAddress ip = IPAddress.Any;
                    //创建对象端口
                    IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(tb_port.Text));
    
                    socketWatch.Bind(point);//绑定端口号
                    ShowMsg("监听成功!");
                    socketWatch.Listen(10);//设置监听
    
                    //创建监听线程
                    Thread thread = new Thread(Listen);
                    thread.IsBackground = true;
                    thread.Start(socketWatch);
                }
                catch { }
               
            }
           
            /// <summary>
            /// 等待客户端的连接 并且创建与之通信的Socket
            /// </summary>
            Socket socketSend;
            void Listen(object o)
            {
                try
                {
                    Socket socketWatch = o as Socket;
                    while (true)
                    {
                        socketSend = socketWatch.Accept();//等待接收客户端连接
                        ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + "连接成功!");
                        //开启一个新线程,执行接收消息方法
                        Thread r_thread = new Thread(Received);
                        r_thread.IsBackground = true;
                        r_thread.Start(socketSend);
                    }
                }
                catch { }
            }
            /// <summary>
            /// 服务器端不停的接收客户端发来的消息
            /// </summary>
            /// <param name="o"></param>
            void Received(object o)
            {
                try
                {
                    Socket socketSend = o as Socket;
                    while (true)
                    {
                        //客户端连接服务器成功后,服务器接收客户端发送的消息
                        byte[] buffer = new byte[1024 * 1024 * 3];
                        //实际接收到的有效字节数
                        int len = socketSend.Receive(buffer);
                        if (len == 0)
                        {
                            break;
                        }
                        string str = Encoding.UTF8.GetString(buffer, 0, len);
                        ShowMsg(socketSend.RemoteEndPoint + ":" + str);
                    }
                }
                catch { }
            }
            /// <summary>
            /// 服务器向客户端发送消息
            /// </summary>
            /// <param name="str"></param>
            void Send(string str) {
                byte[] buffer = Encoding.UTF8.GetBytes(str);
                socketSend.Send(buffer);
            }
    
            void ShowMsg(string msg)
            {
                listBox1.Items.Add(msg + "
    ");
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                Control.CheckForIllegalCrossThreadCalls = false;
            }
    
            private void bt_send_Click(object sender, EventArgs e)
            {
                Send(txt_msg.Text.Trim());
            }
        }
    }
    View Code

     2、客户端

      (1)客户端窗口设计

    namespace SocketClient
    {
        partial class Form1
        {
            /// <summary>
            /// 必需的设计器变量。
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary>
            /// 清理所有正在使用的资源。
            /// </summary>
            /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region Windows 窗体设计器生成的代码
    
            /// <summary>
            /// 设计器支持所需的方法 - 不要
            /// 使用代码编辑器修改此方法的内容。
            /// </summary>
            private void InitializeComponent()
            {
                this.panel1 = new System.Windows.Forms.Panel();
                this.lb_ip = new System.Windows.Forms.Label();
                this.txt_ip = new System.Windows.Forms.TextBox();
                this.txt_port = new System.Windows.Forms.TextBox();
                this.lb_port = new System.Windows.Forms.Label();
                this.bt_connect = new System.Windows.Forms.Button();
                this.textBox1 = new System.Windows.Forms.TextBox();
                this.txt_msg = new System.Windows.Forms.TextBox();
                this.bt_send = new System.Windows.Forms.Button();
                this.panel1.SuspendLayout();
                this.SuspendLayout();
                // 
                // panel1
                // 
                this.panel1.Controls.Add(this.bt_connect);
                this.panel1.Controls.Add(this.txt_port);
                this.panel1.Controls.Add(this.lb_port);
                this.panel1.Controls.Add(this.txt_ip);
                this.panel1.Controls.Add(this.lb_ip);
                this.panel1.Location = new System.Drawing.Point(12, 12);
                this.panel1.Name = "panel1";
                this.panel1.Size = new System.Drawing.Size(463, 75);
                this.panel1.TabIndex = 0;
                // 
                // lb_ip
                // 
                this.lb_ip.AutoSize = true;
                this.lb_ip.Location = new System.Drawing.Point(14, 23);
                this.lb_ip.Name = "lb_ip";
                this.lb_ip.Size = new System.Drawing.Size(23, 12);
                this.lb_ip.TabIndex = 0;
                this.lb_ip.Text = "IP:";
                // 
                // txt_ip
                // 
                this.txt_ip.Location = new System.Drawing.Point(43, 20);
                this.txt_ip.Name = "txt_ip";
                this.txt_ip.Size = new System.Drawing.Size(100, 21);
                this.txt_ip.TabIndex = 1;
                this.txt_ip.Text = "127.0.0.1";
                // 
                // txt_port
                // 
                this.txt_port.Location = new System.Drawing.Point(207, 23);
                this.txt_port.Name = "txt_port";
                this.txt_port.Size = new System.Drawing.Size(100, 21);
                this.txt_port.TabIndex = 3;
                this.txt_port.Text = "2001";
                // 
                // lb_port
                // 
                this.lb_port.AutoSize = true;
                this.lb_port.Location = new System.Drawing.Point(166, 29);
                this.lb_port.Name = "lb_port";
                this.lb_port.Size = new System.Drawing.Size(35, 12);
                this.lb_port.TabIndex = 2;
                this.lb_port.Text = "port:";
                // 
                // bt_connect
                // 
                this.bt_connect.Location = new System.Drawing.Point(313, 9);
                this.bt_connect.Name = "bt_connect";
                this.bt_connect.Size = new System.Drawing.Size(113, 47);
                this.bt_connect.TabIndex = 4;
                this.bt_connect.Text = "连接";
                this.bt_connect.UseVisualStyleBackColor = true;
                this.bt_connect.Click += new System.EventHandler(this.bt_connect_Click);
                // 
                // textBox1
                // 
                this.textBox1.Location = new System.Drawing.Point(12, 103);
                this.textBox1.Multiline = true;
                this.textBox1.Name = "textBox1";
                this.textBox1.Size = new System.Drawing.Size(463, 114);
                this.textBox1.TabIndex = 1;
                // 
                // txt_msg
                // 
                this.txt_msg.Location = new System.Drawing.Point(12, 246);
                this.txt_msg.Multiline = true;
                this.txt_msg.Name = "txt_msg";
                this.txt_msg.Size = new System.Drawing.Size(291, 54);
                this.txt_msg.TabIndex = 2;
                // 
                // bt_send
                // 
                this.bt_send.Location = new System.Drawing.Point(325, 246);
                this.bt_send.Name = "bt_send";
                this.bt_send.Size = new System.Drawing.Size(113, 54);
                this.bt_send.TabIndex = 3;
                this.bt_send.Text = "发送";
                this.bt_send.UseVisualStyleBackColor = true;
                this.bt_send.Click += new System.EventHandler(this.bt_send_Click);
                // 
                // Form1
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(493, 323);
                this.Controls.Add(this.bt_send);
                this.Controls.Add(this.txt_msg);
                this.Controls.Add(this.textBox1);
                this.Controls.Add(this.panel1);
                this.Name = "Form1";
                this.Text = "Form1";
                this.Load += new System.EventHandler(this.Form1_Load);
                this.panel1.ResumeLayout(false);
                this.panel1.PerformLayout();
                this.ResumeLayout(false);
                this.PerformLayout();
    
            }
    
            #endregion
    
            private System.Windows.Forms.Panel panel1;
            private System.Windows.Forms.Label lb_ip;
            private System.Windows.Forms.Button bt_connect;
            private System.Windows.Forms.TextBox txt_port;
            private System.Windows.Forms.Label lb_port;
            private System.Windows.Forms.TextBox txt_ip;
            private System.Windows.Forms.TextBox textBox1;
            private System.Windows.Forms.TextBox txt_msg;
            private System.Windows.Forms.Button bt_send;
        }
    }
    View Code

            (2)客户端逻辑设计

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace SocketClient
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            Socket socketSend;
            private void bt_connect_Click(object sender, EventArgs e)
            {
                try
                {
                    //创建客户端Socket,获得远程ip和端口号
                    socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    IPAddress ip = IPAddress.Parse(txt_ip.Text);
                    IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txt_port.Text));
    
                    socketSend.Connect(point);
                    ShowMsg("连接成功!");
                    //开启新的线程,不停的接收服务器发来的消息
                    Thread c_thread = new Thread(Received);
                    c_thread.IsBackground = true;
                    c_thread.Start();
                }
                catch (Exception){
                    ShowMsg("IP或者端口号错误...");
                }
     
            }
            void ShowMsg(string str)
            {
                textBox1.AppendText(str + "
    ");
            }
            /// <summary>
            /// 接收服务端返回的消息
            /// </summary>
            void Received()
            {
                while (true)
                {
                    try
                    {
                        byte[] buffer = new byte[1024 * 1024 * 3];
                        //实际接收到的有效字节数
                        int len = socketSend.Receive(buffer);
                        if (len == 0)
                        {
                            break;
                        }
                        string str = Encoding.UTF8.GetString(buffer, 0, len);
                        ShowMsg(socketSend.RemoteEndPoint + ":" + str);
                    }
                    catch { }
                }
            } 
            /// <summary>
            /// 向服务器发送消息
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void bt_send_Click(object sender, EventArgs e)
            {
                try
                {
                    string msg = txt_msg.Text.Trim();
                    byte[] buffer = new byte[1024 * 1024 * 3];
                    buffer = Encoding.UTF8.GetBytes(msg);
                    socketSend.Send(buffer);
                }
                catch { }
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                Control.CheckForIllegalCrossThreadCalls = false;
            }
        }
    }
    View Code

      1、服务端

      2、客户端

      

     
  • 相关阅读:
    HDU 1114 Piggy-Bank
    HDU 2955 Robberies
    NTOJ 290 动物统计(加强版)
    POJ 3624 Charm Bracelet
    HDU 2602 Bone Collector
    POJ 1523 SPF(无向图割顶)
    HDU 5311 Hidden String
    HDU 1421 搬寝室
    HDU 1058 Humble Numbers
    POJ 3259 Wormholes(spfa判负环)
  • 原文地址:https://www.cnblogs.com/aijiao/p/10399574.html
Copyright © 2011-2022 走看看