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 + "\r\n"); });
        }
        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 + "\r\n"); });
        }
        /// <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("連接已經斷開!");
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM