本节课创建一个客户端,然后客户端中连接服务器端。
结合前面服务端(TcpListener)和 本节客户端(TcpClient)一步步实现一个TCP聊天工具
概念区分
- 服务端:TcpListener
绑定固定IP + 固定端口(9500),持续被动监听,等待客户端接入,可以同时接纳多个客户端。(它就好比一个卖东西的人,在哪里等待买家到来) - 客户端:TcpClient
不需要手动绑定端口;操作系统自动分配随机临时端口发起主动连接,去对接服务端固定9500端口。
通信双方端口不对等
客户端随机端口 —服务端固定9500
控制台客户端
using System;
using System.Net.Sockets;
namespace TalkClient
{
class Program
{
static void Main(string[] args)
{
// 创建TCP客户端对象
TcpClient tcpClient = new TcpClient();
// 发起连接,连接本机127.0.0.1:9500服务端 如果是其他计算机,可以设置另外一台计算机的ip,服务器端和客户端不一定在同一台电脑
tcpClient.Connect("127.0.0.1", 9500);
// LocalEndPoint:本机客户端地址端口
// RemoteEndPoint:远端服务端地址端口
Console.WriteLine("链接成功,我方端口 {0},服务器端口{1}",
tcpClient.Client.LocalEndPoint,
tcpClient.Client.RemoteEndPoint);
Console.ReadLine();
tcpClient.Close();
}
}
}Code language: JavaScript (javascript)
WinForms 客户端代码
界面控件:
textBoxIP:服务器IPtextBoxPort:服务器端口buttonStart:【连接】按钮textBoxInfo:消息展示框textBoxMsg:待发送消息输入框buttonSend:发送按钮
using System;
using System.Net.Sockets;
using System.Windows.Forms;
namespace SocketChatClient
{
public partial class Form1 : Form
{
TcpClient tcpClient;
public Form1()
{
InitializeComponent();
}
// 连接按钮点击事件
private void buttonStart_Click(object sender, EventArgs e)
{
tcpClient = new TcpClient();
try
{
string ip = textBoxIP.Text;
int port = Convert.ToInt32(textBoxPort.Text);
tcpClient.Connect(ip, port);
textBoxInfo.AppendText($"连接成功!本地端点:{tcpClient.Client.LocalEndPoint}\r\n");
}
catch (Exception ex)
{
MessageBox.Show("连接失败-" + ex.Message);
}
}
}
}Code language: PHP (php)
服务端 + 客户端配合
- 先启动服务端程序,点击启动,
TcpListener.Start()开始监听9500端口 - 再启动客户端程序,点击连接,
TcpClient.Connect()发起TCP三次握手 - 连接成功后,双向通过
NetworkStream收发消息(下一章节内容)
注意
- 连接失败常见原因
- 顺序错误:没有先启动服务端
- IP/端口填写不一致
- 防火墙拦截;跨电脑调试不要使用
127.0.0.1,改用局域网IP
- 端口知识
- 服务端端口固定9500,可以同时接受多个客户端
- 客户端端口由操作系统随机分配,每次运行端口不一样,无需手动指定
- 阻塞警告
窗体程序中直接调用.Connect()会阻塞UI线程。正式项目建议使用异步ConnectAsync,防止窗口卡死。
服务端WinForms回顾(上一节)
using System;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
namespace SocketChatServer
{
public partial class Form1 : Form
{
IPAddress ip;
TcpListener listener;
public Form1()
{
InitializeComponent();
}
private void buttonStart_Click(object sender, EventArgs e)
{
ip = IPAddress.Parse(textBoxIP.Text);
int port = Convert.ToInt32(textBoxPort.Text);
listener = new TcpListener(ip, port);
listener.Start();
textBoxInfo.Text = $"服务器启动 {DateTime.Now.ToShortTimeString()}\r\n" + textBoxInfo.Text;
}
}
}Code language: C# (cs)