C#开发简单的聊天程序
最近在b站看到一个用C#&Socket实现一个简易聊天程序的视频,感觉挺不错的就照着学习了一下,顺便做个笔记。
socket通信原理图:
服务端(WinForm):
C#
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 SocketServer
{
public partial class MainForm : Form
{
public List<Socket> clientList = new List<Socket>();
public MainForm()
{
InitializeComponent();
}
private void startBtn_Click(object sender, EventArgs e)
{
//1、创建socket对象
Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//2、绑定ip和端口
socket.Bind(new IPEndPoint(IPAddress.Parse(ipContent.Text),int.Parse(portContent.Text)));
//3、开启监听
socket.Listen(10);
//4、开始接收客户端消息
ThreadPool.QueueUserWorkItem(new WaitCallback(acceptClient),socket);
this.AppendTxtToShowLog(string.Format("服务器启动成功!")) ;
}
private void acceptClient(object server)
{
Socket socket = server as Socket;
while (true)
{
Socket clientSocket=socket.Accept();//接收客户端连接
clientList.Add(clientSocket);
this.AppendTxtToShowLog(string.Format("客户端{0}连接成功", clientSocket.RemoteEndPoint.ToString()));
//不断接收客户端发来的消息
ThreadPool.QueueUserWorkItem(new WaitCallback(receiveClient),clientSocket);
}
}
private void receiveClient(object client)
{
Socket clientSocket = client as Socket;
byte[] data = new byte[1024 * 1024];
while (true)
{
int len = 0;
try
{
len = clientSocket.Receive(data, 0, data.Length, SocketFlags.None);//接收字节数组,并获取长度
}
catch (Exception)//客户端异常退出
{
try
{
this.AppendTxtToShowLog(string.Format("客户端{0}异常退出", clientSocket.RemoteEndPoint.ToString()));
}
catch (Exception)
{
}
clientList.Remove(clientSocket);
stopConnect(clientSocket);//关闭连接
return;
}
if (len <= 0)//客户端正常退出
{
try
{
this.AppendTxtToShowLog(string.Format("客户端{0}正常退出", clientSocket.RemoteEndPoint.ToString()));
}
catch (Exception)
{
}
clientList.Remove(clientSocket);
stopConnect(clientSocket);//关闭连接
return;
}
string str=Encoding.Default.GetString(data,0,len);//将字节数组转换成字符串
this.AppendTxtToShowLog(string.Format("客户端{0}发来信息:{1}",clientSocket.RemoteEndPoint.ToString(),str));
}
}
//关闭连接
private void stopConnect(Socket clientSocket)
{
if (clientSocket.Connected)
{
try
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close(100);
}
catch (Exception)
{
}
}
}
private void AppendTxtToShowLog(string str)//添加日志记录
{
if (showLog.InvokeRequired)
{
showLog.BeginInvoke(new Action<string>(s =>
{
showLog.Text = string.Format("{0}\r\n{1}", s, this.showLog.Text);
}), str);
}
else
{
showLog.Text = string.Format("{0}\r\n{1}", str, this.showLog.Text);
}
}
private void sendBtn_Click(object sender, EventArgs e)
{
foreach (var clientSocket in clientList)
{
if (clientSocket.Connected)
{
byte[] data = Encoding.Default.GetBytes(this.sendContent.Text);
clientSocket.Send(data,0,data.Length,SocketFlags.None);
}
}
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
foreach (var clientSocket in clientList)
{
if (clientSocket.Connected)
{
try
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
catch (Exception)
{
}
}
}
}
}
}
客户端(WinForm):
C#
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 SocketClient
{
public partial class MainForm : Form
{
public Socket clientSocket { get; set; }
public MainForm()
{
InitializeComponent();
}
private void connectBtn_Click(object sender, EventArgs e)
{
//1、创建socket
Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
clientSocket = socket;
//2、连接服务器(ip+port)
try
{
socket.Connect(IPAddress.Parse(ipContent.Text), int.Parse(portContent.Text));
}
catch (Exception ex)
{
//Thread.Sleep(10);
//connectBtn_Click(this,e);
MessageBox.Show("连接失败");
return;
}
//3、开始接收信息
Thread thread = new Thread(new ParameterizedThreadStart(receiveData));
thread.IsBackground = true;
thread.Start(clientSocket);
}
private void receiveData(object socket)
{
byte[] data = new byte[1024 * 1024];
while (true)
{
int len = 0;
try
{
len = clientSocket.Receive(data, 0, data.Length - 1, SocketFlags.None);
}
catch (Exception)
{
try
{
this.AppendTxtToShowLog(string.Format("服务端{0}异常退出", clientSocket.RemoteEndPoint.ToString()));
}
catch (Exception)
{
}
stopConnect();//关闭连接
return;
}
if (len <= 0)
{
try
{
this.AppendTxtToShowLog(string.Format("服务端{0}正常退出", clientSocket.RemoteEndPoint.ToString()));
}
catch (Exception)
{
}
stopConnect();//关闭连接
return;
}
string str = Encoding.Default.GetString(data,0,len);
AppendTxtToShowLog(string.Format("服务端发来信息:{0}",str));
}
}
//关闭连接
private void stopConnect()
{
if (clientSocket.Connected)
{
try
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close(100);
}
catch (Exception)
{
}
}
}
private void AppendTxtToShowLog(string str)//添加日志记录
{
if (showLog.InvokeRequired)
{
showLog.BeginInvoke(new Action<string>(s =>
{
showLog.Text = string.Format("{0}\r\n{1}", s, this.showLog.Text);
}), str);
}
else
{
showLog.Text = string.Format("{0}\r\n{1}", str, this.showLog.Text);
}
}
private void sendBtn_Click(object sender, EventArgs e)
{
if (clientSocket.Connected)
{
byte[] data = Encoding.Default.GetBytes(sendContent.Text);
clientSocket.Send(data, 0, data.Length, SocketFlags.None);
}
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
//判断是否连接,如果连接则关闭连接
stopConnect();
}
}
}
效果图:
评论