1. 七层协议
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
TCP/UDP属于传输层,IP属于网络层
2. TCP协议
建立有连接的,可靠性高的,无数据丢失的连接。
3. 使用C#实现TCP
3.1 服务器
- 初始化套接字
- 绑定IP、端口号
- 监听
- 接收客户请求
- 收发数据
- 关闭套接字
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 SocketTCPService
{
public partial class ServerForm : Form
{
Socket server;//服务器套接字
Socket client;//接受客户请求后的套接字
byte[] buffer = new byte[1024 * 1024 * 6];//申请6Mb内存
Thread th;//监听线程
Thread receive;//接收数据线程
Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
public ServerForm()
{
InitializeComponent();
}
#region 启动服务器
bool isSer = false;
private void buttonStartServer_Click(object sender, EventArgs e)
{
if(!isSer)
{
//1. 初始化套接字
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
//2. 绑定套接字和端口号
IPAddress ip = IPAddress.Parse(textBoxServerIP.Text);
int port = Convert.ToInt32(textBoxServerPort.Text);
server.Bind(new IPEndPoint(ip, port));
//3. 监听
server.Listen(10);
//4. 开启监听线程
th = new Thread(new ThreadStart(ListenC));
th.IsBackground = true;//设置为后台线程,不需要用户主动关闭
th.Start();
isSer = true;
buttonStartServer.Text = "关闭服务器";
buttonStartServer.BackColor = Color.GreenYellow;
}
else
{
if(server != null)
{
server.Close();
server = null;
}
if (client != null)
{
client.Close();
client = null;
}
if(th != null)
{
th.Abort();
}
if (receive != null)
{
receive.Abort();
}
isSer = false;
buttonStartServer.Text = "启动服务器";
buttonStartServer.BackColor = Color.LightGray;
}
}
#endregion
#region 监听线程
public void ListenC()
{
try
{
while (true)
{
//等待客户的连接请求
client = server.Accept();//阻塞等待
dict.Add(client.RemoteEndPoint.ToString(), client);
//连接成功
Invoke(new MethodInvoker(delegate ()
{
listBoxReceive.Items.Add("连接成功");
comboBoxClient.Items.Add(client.RemoteEndPoint.ToString());
}));
//开启线程
receive = new Thread(new ParameterizedThreadStart(RecData));
receive.IsBackground = true;
receive.Start(client);
}
}
catch (Exception)
{
//throw;
}
}
#endregion
#region 接收数据线程
public void RecData(object obj)
{
Socket Client = (Socket)obj;
int counts = 0;
while (true)
{
try
{
//6. 接收数据
counts = Client.Receive(buffer);
if (counts > 0)
{
//在控件上显示接收到的数据(字符串)
Invoke(new MethodInvoker(delegate ()
{
listBoxReceive.Items.Add(string.Format("客户端{0}说:{1}",
Client.RemoteEndPoint.ToString(), Encoding.Default.GetString(buffer,0,counts)));
}));
}
}
catch(Exception)
{
//throw;
}
}
}
#endregion
#region 发送数据
private void buttonSend_Click(object sender, EventArgs e)
{
if(!isSer)
{
MessageBox.Show("未启动服务器");
}
string ip = comboBoxClient.SelectedItem.ToString();
byte[] buffer = Encoding.Default.GetBytes(textBoxSend.Text);
dict[ip].Send(buffer);
//client.Send(buffer);
}
#endregion
private void buttonClear_Click(object sender, EventArgs e)
{
listBoxReceive.Items.Clear();
}
}
}
3.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.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SocketTCPClient
{
public partial class FormClient : Form
{
#region 构造函数
public FormClient()
{
InitializeComponent();
}
#endregion
#region 变量
Socket ClientSocket;//套接字
byte[] buffer = new byte[1024 * 1024 * 6];
bool isConnect = false;
Thread th;
#endregion
#region 连接服务器 初始化套接字
private void buttonConnect_Click(object sender, EventArgs e)
{
try
{
if(!isConnect)
{
//1. 初始化套接字
ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2. 连接服务器
IPAddress ip = IPAddress.Parse(textBoxIP.Text);
int port = Convert.ToInt32(textBoxPort.Text);
ClientSocket.Connect(new IPEndPoint(ip, port));
isConnect = true;
buttonConnect.Text = "断开服务器";
buttonConnect.BackColor = Color.LawnGreen;
//3. 开启线程
th = new Thread(RecData);
th.IsBackground = true;
th.Start();
}
else
{
if (ClientSocket != null)
{
ClientSocket.Close();
isConnect = false;
buttonConnect.Text = "连接服务器";
buttonConnect.BackColor = Color.LightGray;
}
if(th != null)
{
th.Abort();
th = null;
}
}
}
catch (Exception)
{
MessageBox.Show("连接失败,请检查是否启动了服务器", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
//throw;
}
}
#endregion
#region 接收数据线程
public void RecData()
{
int counts = 0;
while (true)
{
counts = ClientSocket.Receive(buffer);
if (counts > 0)
{
Invoke(new MethodInvoker(delegate ()
{
listBoxRec.Items.Add(string.Format("服务器说:{0}",Encoding.Default.GetString(buffer,0,counts)));
}));
}
}
}
#endregion
#region 发送
private void buttonSend_Click(object sender, EventArgs e)
{
if(isConnect)
{
byte[] buffer = Encoding.Default.GetBytes(textBoxSend.Text);
ClientSocket.Send(buffer);
}
else
{
MessageBox.Show("客户端未连接到服务器", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
#endregion
private void buttonClear_Click(object sender, EventArgs e)
{
listBoxRec.Items.Clear();
}
}
}