服务器
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.Tasks;
using System.Windows.Forms;
namespace ChatDemo01
{
public partial class MainFrm : Form
{
// 定义网络组件
private TcpListener listener;
private TcpClient client;
private NetworkStream stream;
public MainFrm()
{
InitializeComponent();
}
// “开始”按钮点击事件,用于启动服务器并监听客户端连接
private void btnStart_Click(object sender, EventArgs e)
{
ConnectToClient(txtIP.Text, int.Parse(txtPort.Text));
}
#region 启动服务器并监听客户端连接的方法
// 启动服务器并监听客户端连接的方法
private void ConnectToClient(string ipAddress, int port)
{
try
{
listener = new TcpListener(IPAddress.Parse(ipAddress), port);
listener.Start();
AppendTextToTxtLog("服务器正在监听...");
// 使用线程池接受客户端连接,避免阻塞UI线程
ThreadPool.QueueUserWorkItem(AcceptClientConnect, listener);
}
catch (Exception ex)
{
AppendTextToTxtLog($"连接失败: {ex.Message}");
}
}
#endregion
#region 接受客户端连接的回调方法
// 接受客户端连接的回调方法
private void AcceptClientConnect(object state)
{
listener = (TcpListener)state;
client = listener.AcceptTcpClient();
AppendTextToTxtLog("客户端已连接");
stream = client.GetStream(); // 获取网络流以便读写操作
ThreadPool.QueueUserWorkItem(ReceiveData, client); // 开始接收客户端消息
}
#endregion
#region 发送消息到客户端
// 发送消息到客户端
private void SendMessage(string message)
{
if (client != null && client.Connected)
{
try
{
byte[] bytes = Encoding.UTF8.GetBytes(message); // 编码消息为字节流
stream.Write(bytes, 0, bytes.Length);
AppendTextToTxtLog("消息已发送。");
}
catch (Exception ex)
{
AppendTextToTxtLog($"发送消息时出错: {ex.Message}");
}
}
else
{
AppendTextToTxtLog("未连接到客户端。");
}
}
#endregion
#region 接收客户端消息的方法
// 接收客户端消息的方法
private void ReceiveData(object state)
{
client = (TcpClient)state;
byte[] data = new byte[1024 * 1024]; // 缓冲区大小
while (true)
{
try
{
int len = stream.Read(data, 0, data.Length);
if (len > 0)
{
string message = Encoding.UTF8.GetString(data, 0, len);
AppendTextToTxtLog($"收到消息: {message}");
// 简单回显消息给客户端
byte[] response = Encoding.UTF8.GetBytes(message);
stream.Write(response, 0, response.Length);
stream.Flush();
}
}
catch (Exception ex)
{
AppendTextToTxtLog($"接收数据时出错: {ex.Message}");
break; // 发生异常时退出循环
}
}
}
#endregion
#region 往日志文本框追加显示信息的方法
// 往日志文本框追加显示信息的方法,考虑了线程安全
public void AppendTextToTxtLog(string txt)
{
if (txtLog.InvokeRequired)
{
txtLog.Invoke((MethodInvoker)(() => txtLog.Text += $"{txt}\r\n"));
}
else
{
txtLog.Text += $"{txt}\r\n";
}
}
#endregion
#region 发送按钮点击事件
// 发送按钮点击事件
private void btnSendMsg_Click(object sender, EventArgs e)
{
SendMessage(txtMsg.Text);
}
// 关闭窗口前确保关闭客户端连接
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (client != null && client.Connected)
{
client.Close();
AppendTextToTxtLog("服务器已关闭。");
}
}
#endregion
}
}
客户端
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace SocketClient01
{
public partial class MainFrm : Form
{
private TcpClient client;
private NetworkStream stream;
// 构造函数初始化
public MainFrm()
{
InitializeComponent();
}
// 连接按钮点击事件,尝试连接服务器
private void btnConnect_Click(object sender, EventArgs e)
{
try
{
client = new TcpClient();
client.Connect(txtIP.Text, int.Parse(txtPort.Text)); // 使用IP地址和端口连接服务器
AppendTextToTxtLog("已成功连接到服务器");
stream = client.GetStream(); // 初始化网络流
// 创建并启动后台线程用于接收服务器数据
Thread receiveThread = new Thread(ReceiveData);
receiveThread.IsBackground = true; // 设置为后台线程,程序退出时自动关闭
receiveThread.Start(client); // 传递客户端实例给线程
}
catch (SocketException se)
{
AppendTextToTxtLog($"连接服务器失败: {se.Message}");
}
catch (FormatException fe)
{
AppendTextToTxtLog($"端口号格式错误: {fe.Message}");
}
}
#region 接收服务器数据的方法
// 接收服务器数据的方法
private void ReceiveData(object state)
{
TcpClient client = (TcpClient)state;
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[1024];
while (client.Connected)
{
try
{
int received = stream.Read(buffer, 0, buffer.Length);
if (received > 0)
{
string message = Encoding.UTF8.GetString(buffer, 0, received);
AppendTextToTxtLog($"接收到服务器消息: {message}");
}
}
catch (IOException) // 当连接断开时会抛出此异常
{
AppendTextToTxtLog("与服务器的连接已断开。");
break;
}
}
client.Close(); // 断开连接后关闭客户端
}
#endregion
#region 往日志文本框追加显示信息的方法
// 往日志文本框追加显示信息的方法,考虑了线程安全
public void AppendTextToTxtLog(string txt)
{
if (txtLog.InvokeRequired)
{
txtLog.Invoke((MethodInvoker)(() => txtLog.Text += $"{txt}\r\n"));
}
else
{
txtLog.Text += $"{txt}\r\n";
}
}
#endregion
#region 发送消息按钮点击事件
// 发送消息按钮点击事件
private void btnSendMsg_Click(object sender, EventArgs e)
{
if (client == null || !client.Connected)
{
AppendTextToTxtLog("未连接到服务器。");
return;
}
try
{
string message = txtMsg.Text.Trim();
byte[] data = Encoding.UTF8.GetBytes(message);
stream.Write(data, 0, data.Length);
stream.Flush();
AppendTextToTxtLog("消息已发送。");
txtMsg.Clear(); // 发送后清空输入框
}
catch (Exception ex)
{
AppendTextToTxtLog($"发送消息时出错: {ex.Message}");
}
}
#endregion
}
}