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="schemas.microsoft/winfx/2006/xaml/presentation"
xmlns:x="schemas.microsoft/winfx/2006/xaml"
xmlns:d="schemas.microsoft/expression/blend/2008"
xmlns:mc="/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="schemas.microsoft/winfx/2006/xaml/presentation"
xmlns:x="schemas.microsoft/winfx/2006/xaml"
xmlns:d="schemas.microsoft/expression/blend/2008"
xmlns:mc="/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;
socket通信在哪一层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("连接已经断开!");
}
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论