zoukankan      html  css  js  c++  java
  • C# Socket通信DEMO

    一、套接字(socket)概念

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

    二、建立socket连接

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

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

    三、服务端与客户端代码

    1.服务端前台XMAL

    <Window x:Class="WPFAPP.MainWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:WPFAPP"
             mc:Ignorable="d"
             Title="服务端" Height="350" Width="525" Loaded="Window_Loaded" >
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="50*"/>
                <RowDefinition Height="190*"/>
                <RowDefinition Height="81*"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <WrapPanel VerticalAlignment="Center">
                    <Label Padding="5">IP:</Label>
                    <TextBox Padding="3" Width="150" Name="IP"></TextBox>
                    <Label Padding="5">Port:</Label>
                    <TextBox Padding="3" Width="100" Name="Port"></TextBox>
                    <Button Padding="3" Margin="3" Click="Start_View_Click">开始监听</Button>
                    <Button Padding="3" Margin="3" Click="Stop_Click">停止监听</Button>
                </WrapPanel>
            </Grid>
            <Grid Grid.Row="1">
                <ListBox Name="ListConnet"></ListBox>
            </Grid>
            <Grid Grid.Row="2">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="405*"/>
                    <ColumnDefinition Width="113*"/>
                </Grid.ColumnDefinitions>
    
                <TextBox Name="SentConnet"></TextBox>
                <Button Grid.Column="1" Click="Send_Click">发送</Button>
    
            </Grid>
        </Grid>
    </Window>

    2.服务端后台代码

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Windows;
    
    namespace WPFAPP
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
            Socket socketSend;
            private void Start_View_Click(object sender, RoutedEventArgs 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(Port.Text));
                    socketWatch.Bind(point);//绑定端口号
                    ShowMsg("监听成功!");
                    socketWatch.Listen(10);//设置监听
                                           //创建监听线程
                    Thread thread = new Thread(Listen);
                    thread.IsBackground = true;
                    thread.Start(socketWatch);
                }
                catch { }
            }
            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)
            {
                Dispatcher.Invoke(() => { ListConnet.Items.Add(msg + "
    "); });
            }
            private void Send_Click(object sender, RoutedEventArgs e)
            {
                Send(SentConnet.Text.Trim());
            }
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
            }
            private void Stop_Click(object sender, RoutedEventArgs e)
            {
                socketSend.Close();
                ShowMsg("已经停止监听!");
            }
        }
    }

    3.客户端前台XMAL

    <Window x:Class="WPFClient.MainWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:WPFClient"
             mc:Ignorable="d"
             Title="客户端" Height="350" Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="50*"/>
                <RowDefinition Height="50*"/>
                <RowDefinition Height="200
                               *"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <WrapPanel VerticalAlignment="Center">
                    <Label Padding="5">IP:</Label>
                    <TextBox Padding="3" Width="150" Name="IP"></TextBox>
                    <Label Padding="5">Port:</Label>
                    <TextBox Padding="3" Width="100" Name="Port"></TextBox>
                    <Button Padding="3" Margin="3" Click="Start_View_Click">连接</Button>
                    <Button Padding="3" Margin="3" Click="Stop_Click">断开连接</Button>
                </WrapPanel>
            </Grid>
            <Grid Grid.Row="1">
                <TextBox Name="ListConnet"></TextBox>
            </Grid>
            <Grid Grid.Row="2">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="405*"/>
                    <ColumnDefinition Width="113*"/>
                </Grid.ColumnDefinitions>
                <TextBox Name="SentConnet"></TextBox>
                <Button Grid.Column="1" Click="Send_Click">发送</Button>
            </Grid>
        </Grid>
    </Window>

    4.客户端后台代码

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Windows;
    
    namespace WPFClient
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.IP.Text = "127.0.0.1";
                this.Port.Text = "5000";
                this.SentConnet.Text= @"发送消息";
            }
            Socket socketSend;
            private void Start_View_Click(object sender, RoutedEventArgs e)
            {
                try
                {
                    //创建客户端Socket,获得远程ip和端口号
                    socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    IPAddress ip = IPAddress.Parse(IP.Text);
                    IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(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)
            {
                Dispatcher.Invoke(() => { ListConnet.AppendText(str + "
    "); });
            }
            /// <summary>
            /// 接收服务端返回的消息
            /// </summary>
            void Received()
            {
                while (true)
                {
                    try
                    {
                        byte[] buffer = new byte[1024 * 1024 * 3];
                        //实际接收到的有效字节数
                        int len = socketSend.Receive(buffer);
                        if (len == 0)
                        {
                            continue;
                        }
                        string str = Encoding.UTF8.GetString(buffer, 0, len);
                        ShowMsg("接收到的服务端数据:" + socketSend.RemoteEndPoint + ":" + str);
                    }
                    catch
                    {
    
                    }
                }
            }
            private void Send_Click(object sender, RoutedEventArgs e)
            {
                try
                {
                    string msg = SentConnet.Text.Trim();
                    byte[] buffer = new byte[1024 * 1024 * 3];
                    buffer = Encoding.UTF8.GetBytes(msg);
                    socketSend.Send(buffer);
                }
                catch { }
            }
            private void Stop_Click(object sender, RoutedEventArgs e)
            {
                socketSend.Close();
                ShowMsg("连接已经断开!");
            }
        }
    }
  • 相关阅读:
    B站排行榜第一的视频,看看5W弹幕都在说些什么?
    手把手教你如何用Python获取爱奇艺电视剧弹幕数据
    Python爬虫中最重要、最常见、一定要熟练掌握的库
    机器学习
    nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)
    14、ERROR: for proxy Cannot start service proxy: driver failed **** Error starting userland proxy: listen tcp 0.0.0.0:80: listen: address already in use
    13、file /usr/bin/docker from install of docker-ce-18.03.0.ce-1.el7.centos.x86_64 conflicts with file from package docker-common-2:1.13.1-203.git0be3e21.el7.centos.x86_64
    12、Error response from daemon: Get https://192.168.247.151/v2/: dial tcp 192.168.247.151:443: connect: connection refused
    Selenium无法定位元素的九种解决方案
    Linux安装Oracle数据库SQLPlus客户端
  • 原文地址:https://www.cnblogs.com/jasonlai2016/p/11869054.html
Copyright © 2011-2022 走看看