-
基本概念
- IP/TCP:IP(Internet Protocol)即互联网协议,是一种用于在网络中寻址和路由数据包的协议。它为每个连接到互联网的设备分配一个唯一的 IP 地址,使得数据能够在不同的网络节点之间传输。TCP(Transmission Control Protocol)是传输控制协议,它建立在 IP 协议之上,提供可靠的、面向连接的通信服务。TCP 通过一系列机制,如三次握手建立连接、序列号和确认应答、滑动窗口进行流量控制、超时重传等,保证数据能够准确无误地从源端发送到目的端。
- Socket 通信:Socket(套接字)是一种应用层与 TCP/IP 协议族通信的中间软件抽象层。它可以看作是在应用程序和网络协议栈之间的一个接口,通过 Socket,应用程序可以方便地使用 IP/TCP 等网络协议进行通信。简单来说,Socket 是对网络通信进行编程的一种接口机制。
-
相互关系
- Socket 基于 IP/TCP 实现通信功能:Socket 提供了一套函数或方法,程序员可以使用这些接口来调用底层的 IP/TCP 协议功能。例如,在使用 Socket 进行网络编程时,当创建一个 TCP 套接字并调用相关函数进行连接操作时,实际上是在底层利用 TCP 协议的三次握手过程来建立连接。发送和接收数据的操作也是通过 TCP 的可靠传输机制来实现的,而 IP 协议则负责数据的路由和寻址,将数据从源 Socket 发送到目标 Socket 对应的 IP 地址。
- IP/TCP 通过 Socket 提供给应用程序访问接口:IP/TCP 协议本身是比较复杂的网络协议,普通的应用程序很难直接使用这些协议进行通信。Socket 就像是一座桥梁,将复杂的 IP/TCP 协议封装成应用程序可以理解和使用的接口。例如,一个简单的网络聊天应用程序,开发人员可以使用 Socket 提供的接口(如创建套接字、绑定端口、监听连接、发送和接收消息等操作),而不需要深入了解 IP/TCP 协议的细节,就可以实现聊天程序的网络通信功能。
-
通信过程示例
- 假设应用程序 A 要和应用程序 B 进行通信。首先,应用程序 A 通过 Socket API(应用程序编程接口)创建一个 Socket,指定使用 TCP 协议,并绑定一个本地端口。然后,应用程序 A 通过 Socket 发送一个连接请求,这个请求在底层通过 IP 协议进行寻址,找到应用程序 B 所在的设备 IP 地址,再通过 TCP 协议的三次握手过程与应用程序 B 建立连接。一旦连接建立成功,应用程序 A 和 B 就可以通过 Socket 接口发送和接收数据,这些数据在网络中通过 IP 进行路由,通过 TCP 进行可靠传输,确保数据能够正确地在两个应用程序之间传递。
-
应用场景优势
- 广泛适用性:这种基于 Socket 和 IP/TCP 的通信方式被广泛应用于各种网络应用中。从简单的客户端 - 服务器应用(如网页浏览,浏览器作为客户端通过 Socket 和服务器建立 TCP 连接进行网页内容的获取)到复杂的分布式系统通信(如企业级的分布式数据库系统,不同节点之间通过 Socket 和 IP/TCP 进行数据同步和交互)都离不开这种通信方式。
- 可靠性和灵活性:由于 TCP 提供了可靠的通信机制,结合 Socket 方便的编程接口,使得开发人员能够构建稳定、灵活的网络应用。例如,在远程文件传输应用中,利用 Socket 和 IP/TCP 可以确保文件数据完整、准确地在不同设备之间传输,并且可以根据实际情况(如网络带宽、文件大小等)灵活调整传输策略。
----------------------------调试工具(TCP Server服务器端、TCP Client客户端)
1.客户端连接服务器端(需要对应服务器端IP及端口号)

-------------------------手搓Socket服务器端及客户端
1.服务器端

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.Threading.Tasks;
using System.Windows.Forms;
namespace Server端
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//创建Socket
//套接字:进行网络链接字面变量
public Socket socket;//用于通信
public Socket ServerSocket;//服务器的监听
public Socket SocketAccept;//用来接收客户端的套接字
//创建一个线程 用于监听
Thread Thread1;
//接收用户数据线程
Thread Thread2;
//开启服务器事件
private void button1_Click(object sender, EventArgs e)
{
//关闭选中状态 防止再次生成链接对象
button1.Enabled = false;
button2.Enabled = true;
//创建服务器链接对象
//1.协议类型
//2.链接套接字的双向数据流
//3.设置TCP协议
ServerSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//设置IP地址
//IPAddress.Parse 将字符串转化为IP地址的实例
IPAddress ip = IPAddress.Parse(textBox1.Text);
//设置端口号
int Port = Convert.ToInt32(textBox2.Text);
//生成链接对象
IPEndPoint iPEndPoint = new IPEndPoint(ip,Port);
//服务器调用.bind 绑定ip地址
ServerSocket.Bind(iPEndPoint);
//监听的数量
ServerSocket.Listen(20);
//客户端与服务器端之间数据传输 一对多
//开启多线程
//实例话线程 方法的名称 去做的事情
Thread1 = new Thread(Fun);
//将线程 设置为后台线程
Thread1.IsBackground = true;
//开启线程
Thread1.Start(ServerSocket);
}
//Thread1方法
// 线程 形参类型 使用object 保证你的数据不会丢失
private void Fun(object Obj)
{
//接收Socket对象
SocketAccept = Obj as Socket;
try
{
while (true)
{
//添加线程阻塞 当未有客户端连接时不执行后续代码 知道有客户端链接 才去执行
socket = SocketAccept.Accept();
//当用户链接上之后 链接信息 显示在窗体上
//线程 直接显示在窗体上 线程错误 使用委托
//封装方法
// SocketAccept.RemoteEndPoint 链接对象的IP地址
AddMsg($"{DateTime.Now.ToString("HH-mm-ss")},{socket.RemoteEndPoint}链接成功~~");
//客户端 发送数据 展示
Thread2 = new Thread(Display);
Thread2.Start(socket);
}
}
catch (Exception)
{
throw;
}
}
//接收客户端数据显示事件
private void Display(Object Obj)
{
socket = Obj as Socket;
//一直处于监听状态......
while (true)
{
try
{
//接收传数数据 byte -》编码 字符串
byte[] by = new byte[socket.ReceiveBufferSize];
//将字节添加至数组中
//Num是接收数量
int Num = socket.Receive(by);
//Num = 0 则表示本次未接收到客户端所传送消息 则不需要进行后续编码及显示操作
if (Num == 0)
{
//暂停or终止线程
Thread2.Abort();
//搭配whlie + breck;终止...
break;
}
//编码操作
//string Str = Encoding.UTF8.GetString(by);
string Str = Encoding.Default.GetString(by);
AddMsg(Str);
}
catch (Exception)
{
throw;
}
}
}
//委托 方法 避免线程错误
private void AddMsg(string str) {
//异步封装函数
richTextBox1.BeginInvoke(new Action<string>(S => {
richTextBox1.Text += S;
richTextBox1.Text += "\n";
}), str);
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
//将添加内容起始点 放在了最后
richTextBox1.SelectionStart = richTextBox1.Text.Length;
//ScrollToCaret 将滚动条设置至光标or所添加内容区域
richTextBox1.ScrollToCaret();
}
//关闭服务器事件
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = true;
//关闭所有进程
if (socket != null) {
socket.Shutdown(SocketShutdown.Both);
socket.Close();
Thread2.Abort();
}
SocketAccept.Close();
ServerSocket.Close();
Thread1.Abort();
}
//发送消息
private void button3_Click(object sender, EventArgs e)
{
//拿取richTextBox2中信息 字符串-》byte
//richTextBox2.Text;
byte[] by = Encoding.Default.GetBytes(richTextBox2.Text);
//发送数据
socket.Send(by);
//内容清空
richTextBox2.Text = "";
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
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.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
namespace Custom端
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//客户端链接
public Socket CustomSocket;
//创建一个线程 用于监听
Thread Thread1;
private void button1_Click(object sender, EventArgs e)
{
//关闭选中状态 防止再次生成链接对象
button1.Enabled = false;
button2.Enabled = true;
//客户端 与服务器 建立链接...目标ip+端口 生成一个链接对象
CustomSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//设置IP地址
//IPAddress.Parse 将字符串转化为IP地址的实例
IPAddress ip = IPAddress.Parse(textBox1.Text);
//设置端口号
int Port = Convert.ToInt32(textBox2.Text);
//生成链接对象
IPEndPoint iPEndPoint = new IPEndPoint(ip, Port);
//客户端与服务器建立链接
CustomSocket.Connect(iPEndPoint);
AddMsg($"{DateTime.Now.ToString("HH-mm-ss")}链接成功~~");
//服务器调用.bind 绑定ip地址
// CustomSocket.Bind(iPEndPoint);
//监听的数量
// CustomSocket.Listen(20);
//客户端与服务器端之间数据传输 一对多
//开启多线程
//实例话线程 方法的名称 去做的事情
Thread1 = new Thread(Fun);
//将线程 设置为后台线程
Thread1.IsBackground = true;
//开启线程
Thread1.Start(CustomSocket);
}
//接收消息
private void Fun(object Obj)
{
//接收Socket对象
Socket SocketAccept = Obj as Socket;
while (true)
{
byte[] by = new byte[SocketAccept.ReceiveBufferSize];
int num = SocketAccept.Receive(by);
if(num == 0)
{
break;
}
string Str = Encoding.Default.GetString(by);
AddMsg(Str);
}
}
//委托 方法 避免线程错误
private void AddMsg(string str)
{
//异步封装函数
richTextBox1.BeginInvoke(new Action<string>(S => {
richTextBox1.Text += S;
richTextBox1.Text += "\n";
}), str);
}
//断开事件
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = true;
//关闭所有进程
if (CustomSocket != null)
{
CustomSocket.Shutdown(SocketShutdown.Both);
CustomSocket.Close();
Thread1.Abort();
}
}
private void button3_Click(object sender, EventArgs e)
{
byte[] by = Encoding.Default.GetBytes(richTextBox2.Text);
//发送数据
CustomSocket.Send(by);
//内容清空
richTextBox2.Text = "";
}
}
}

1万+

被折叠的 条评论
为什么被折叠?



