• 简单的C# Socket通信实例


    一、套接字(socket)概念

           套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
      应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应 用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

    二、建立socket连接

           建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
      套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

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

    三、服务端与客户端代码

    服务端前台XMAL

     1 <Window x:Class="Socket通信.MainWindow"
     2          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     5          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     6          xmlns:local="clr-namespace:Socket通信"
     7          mc:Ignorable="d"
     8          Title="服务端" Height="350" Width="525" Loaded="Window_Loaded" >
     9      <Grid>
    10          <Grid.RowDefinitions>
    11              <RowDefinition Height="50*"/>
    12              <RowDefinition Height="190*"/>
    13              <RowDefinition Height="81*"/>
    14          </Grid.RowDefinitions>
    15          <Grid Grid.Row="0">
    16              <WrapPanel VerticalAlignment="Center">
    17                  <Label Padding="5">IP:</Label>
    18                  <TextBox Padding="3" Width="150" Name="IP"></TextBox>
    19                  <Label Padding="5">Port:</Label>
    20                  <TextBox Padding="3" Width="100" Name="Port"></TextBox>
    21                  <Button Padding="3" Margin="3" Click="Start_View_Click">开始监听</Button>
    22                  <Button Padding="3" Margin="3" Click="Stop_Click">停止监听</Button>
    23              </WrapPanel>
    24          </Grid>
    25          <Grid Grid.Row="1">
    26              <ListBox Name="ListConnet"></ListBox>
    27          </Grid>
    28          <Grid Grid.Row="2">
    29              <Grid.ColumnDefinitions>
    30                  <ColumnDefinition Width="405*"/>
    31                  <ColumnDefinition Width="113*"/>
    32              </Grid.ColumnDefinitions>
    33             
    34                  <TextBox Name="SentConnet"></TextBox>
    35                  <Button Grid.Column="1" Click="Send_Click">发送</Button>
    36           
    37          </Grid>
    38      </Grid>
    39  </Window>
    View Code

    服务端后台代码

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

    客户端前台XMAL

     1 <Window x:Class="Socket_Client.MainWindow"
     2          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     5          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     6          xmlns:local="clr-namespace:Socket_Client"
     7          mc:Ignorable="d"
     8          Title="客户端" Height="350" Width="525">
     9     <Grid>
    10          <Grid.RowDefinitions>
    11              <RowDefinition Height="50*"/>
    12              <RowDefinition Height="190*"/>
    13              <RowDefinition Height="81*"/>
    14          </Grid.RowDefinitions>
    15          <Grid Grid.Row="0">
    16              <WrapPanel VerticalAlignment="Center">
    17                  <Label Padding="5">IP:</Label>
    18                  <TextBox Padding="3" Width="150" Name="IP"></TextBox>
    19                  <Label Padding="5">Port:</Label>
    20                  <TextBox Padding="3" Width="100" Name="Port"></TextBox>
    21                  <Button Padding="3" Margin="3" Click="Start_View_Click">连接</Button>
    22                  <Button Padding="3" Margin="3" Click="Stop_Click">断开连接</Button>
    23              </WrapPanel>
    24          </Grid>
    25          <Grid Grid.Row="1">
    26              <TextBox Name="ListConnet"></TextBox>
    27          </Grid>
    28          <Grid Grid.Row="2">
    29              <Grid.ColumnDefinitions>
    30                  <ColumnDefinition Width="405*"/>
    31                  <ColumnDefinition Width="113*"/>
    32              </Grid.ColumnDefinitions>
    33 
    34  
    35 
    36             <TextBox Name="SentConnet"></TextBox>
    37              <Button Grid.Column="1" Click="Send_Click">发送</Button>
    38 
    39         </Grid>
    40      </Grid>
    41  </Window>
    View Code

    客户端后台代码

      1 using System;
      2  using System.Collections.Generic;
      3  using System.Linq;
      4  using System.Net;
      5  using System.Net.Sockets;
      6  using System.Text;
      7  using System.Threading;
      8  using System.Threading.Tasks;
      9  using System.Windows;
     10  using System.Windows.Controls;
     11  using System.Windows.Data;
     12  using System.Windows.Documents;
     13  using System.Windows.Input;
     14  using System.Windows.Media;
     15  using System.Windows.Media.Imaging;
     16  using System.Windows.Navigation;
     17  using System.Windows.Shapes;
     18 
     19  
     20 
     21 namespace Socket_Client
     22  {
     23      /// <summary>
     24      /// MainWindow.xaml 的交互逻辑
     25     /// </summary>
     26      public partial class MainWindow : Window
     27      {
     28          public MainWindow()
     29          {
     30              InitializeComponent();
     31          }
     32          Socket socketSend;
     33 
     34  
     35 
     36         private void Start_View_Click(object sender, RoutedEventArgs e)
     37          {
     38              try
     39                {
     40                                  //创建客户端Socket,获得远程ip和端口号
     41                     socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     42                      IPAddress ip = IPAddress.Parse(IP.Text);
     43                      IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(Port.Text));
     44                 
     45                      socketSend.Connect(point);
     46                      ShowMsg("连接成功!");
     47                                   //开启新的线程,不停的接收服务器发来的消息
     48                     Thread c_thread = new Thread(Received);
     49                      c_thread.IsBackground = true;
     50                      c_thread.Start();
     51                 }
     52               catch (Exception)
     53              {
     54                 ShowMsg("IP或者端口号错误...");
     55              }
     56             
     57 
     58  
     59 
     60         }
     61          void ShowMsg(string str)
     62           {
     63 
     64  
     65 
     66             Dispatcher.Invoke(() => { ListConnet.AppendText(str + "
    "); });
     67          }
     68          /// <summary>
     69           /// 接收服务端返回的消息
     70          /// </summary>
     71          void Received()
     72          {
     73              while (true)
     74              {
     75                try
     76                {
     77                     byte[] buffer = new byte[1024 * 1024 * 3];
     78                     //实际接收到的有效字节数
     79                     int len = socketSend.Receive(buffer);
     80                     if (len == 0)
     81                     {
     82                         continue;
     83                       }
     84                      string str = Encoding.UTF8.GetString(buffer, 0, len);
     85                      ShowMsg("接收到的服务端数据:" + socketSend.RemoteEndPoint + ":" + str);
     86                  }
     87                  catch
     88                  {
     89 
     90  
     91 
     92                 }
     93             }
     94          }
     95 
     96  
     97 
     98         private void Send_Click(object sender, RoutedEventArgs e)
     99          {
    100              try
    101              {
    102                       string msg = SentConnet.Text.Trim();
    103                       byte[] buffer = new byte[1024 * 1024 * 3];
    104                       buffer = Encoding.UTF8.GetBytes(msg);
    105                       socketSend.Send(buffer);
    106                }
    107              catch { }
    108 
    109  
    110 
    111         }
    112 
    113         private void Stop_Click(object sender, RoutedEventArgs e)
    114          {
    115              socketSend.Close();
    116              ShowMsg("连接已经断开!");
    117          }
    118      }
    119  }
    View Code

    运行结果

  • 相关阅读:
    Fastjson1.2.68 绕Autotype的一点总结
    MySQL外键约束冲突异常:com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (...)
    SO_REUSEADDR
    Live2d Test Env
    Mac上使用virtualenv配置Python虚拟环境
    Mac环境下替换pip源方法
    Mac上安装Python3教程
    【ASP.NET Core学习】使用JWT认证授权
    LeetCode 110. 平衡二叉树 | Python
    LeetCode 733. 图像渲染 | Python
  • 原文地址:https://www.cnblogs.com/TechnologyDictionary/p/10423068.html
Copyright © 2020-2023  润新知