c#聊天程序
框架模型搭建
用Windos窗口来搭建模型为所用的工具Button,Label,TextBox(名字应在建立时弄好)
Socket聊天程序服务器端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.IO;
namespace WindowsFormsApplication1
{
public partial class MainFrm : Form
{
List<Socket> ClientProxSocketList = new List<Socket>();
public MainFrm()
{
InitializeComponent();
}
private Socket socket;
private void button1_Click_1(object sender, EventArgs e)
{
//1.创建Socket
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2.绑定端口ip
IPAddress ip = IPAddress.Any;
IPEndPoint port = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
socket.Bind(port);
//socket.Bind(new IPEndPoint(IPAddress.Parse(txtIp.Text), int Parse(txtPort.Text)));
//开启监听
socket.Listen(10);//等待连接的队列:同时100多连接请求,只能处理一个连接,队列里面放10个等待连接的客户端,其他返回错误信息。
//开始接受客户端的连接
ThreadPool.QueueUserWorkItem(new WaitCallback(this.AcceptClientConnect), socket);
}
public void AcceptClientConnect(object socket)
{
var serverSocket = socket as Socket;
this.AppendTextToTxtlog("服务器端开始接受客户端连接");
while (true)
{
var proxSocket = serverSocket.Accept();
this.AppendTextToTxtlog(string.Format("客户端:{0}连接上了", proxSocket.RemoteEndPoint.ToString()));
ClientProxSocketList.Add(proxSocket);
//不停接受当前连接的客户端发来的消息
ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveData), proxSocket);
}
}
//接收客户端的消息
public void ReceiveData(object socket)
{
var proxSocket = socket as Socket;
byte[] data = new byte[1024 * 1024];
while (true)
{
int len = 0;
try
{
len = proxSocket.Receive(data, 0, data.Length, SocketFlags.None);
}
catch (Exception ex)
{
//异常退出
AppendTextToTxtlog(string.Format("客户端:{0}非正常退出", proxSocket.RemoteEndPoint.ToString()));
ClientProxSocketList.Remove(proxSocket);
StopConnetct(proxSocket);
return;
}
if (len <= 0)
{
//客户端正常退出
AppendTextToTxtlog(string.Format("客户端:{0}正常退出", proxSocket.RemoteEndPoint.ToString()));
ClientProxSocketList.Remove(proxSocket);
StopConnetct(proxSocket);
return;//让方法结束,终结当前接收客户端数据异步线程
}
//把接收的数据放到文本框上去
string str = Encoding.Default.GetString(data, 0, len);
AppendTextToTxtlog(string.Format("接收到客户端:{0}的消息是:{1}", proxSocket.RemoteEndPoint.ToString(), str));
}
}
private void StopConnetct(Socket proxSocket)
{
try
{
if (proxSocket.Connected)
{
proxSocket.Shutdown(SocketShutdown.Both);
proxSocket.Close(100);
}
}
catch (Exception ex)
{
}
}
//往日志的文本框上追加数据
public void AppendTextToTxtlog(string txt)
{
//Action<string> sdel = a => { };
//sdel = new Action<string>(a => { });
//sdel("sss");
//sdel.Invoke("sss");
//sdel.BeginInvoke("sss", null, null);
if (txtlog.InvokeRequired)
{
txtlog.BeginInvoke(new Action<string>(s =>
{
this.txtlog.Text = string.Format("{0}\r\n{1}", txt, txtlog.Text);
}), txt);
//同步方法
txtlog.Invoke(new Action<string>(s =>
{
this.txtlog.Text = string.Format("{0}\r\n{1}", txt, txtlog.Text);
}), txt);
}
else
{
this.txtlog.Text = string.Format("{0}\r\n{1}", txt, txtlog.Text);
}
}
#region 发送字符串
//发送消息
private void btnSendMsg_Click(object sender, EventArgs e)
{
foreach (var proxSocket in ClientProxSocketList)
{
if (proxSocket.Connected)
{
//原始的字符串转换成的字节数组。
byte[] data = Encoding.Default.GetBytes(txtMsg.Text);
//对原始的数据组加上协议的头部字节
byte[] result = new byte[data.Length + 1];
//设置当前的协议头部字节 是1:1代表字符串
result[0] = 1;
//把原始的数据放到,最终的字节数组里去
Buffer.BlockCopy(data, 0, result, 1, data.Length);
proxSocket.Send(result, 0, result.Length, SocketFlags.None);
}
}
}
#endregion
private void txtlog_TextChanged(object sender, EventArgs e)
{
}
private void MainFrm_Load(object sender, EventArgs e)
{
}
#region 发送文件
private void button2_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() != DialogResult.OK)
{
return;
}
byte[] data = File.ReadAllBytes(ofd.FileName);
byte[] result = new byte[data.Length + 1];
result[0] = 3;
Buffer.BlockCopy(data, 0, result, 1, data.Length);
foreach (var proxSocket in ClientProxSocketList)
{
if (!proxSocket.Connected)
{
continue;
}
//把要发送的文件读取出来
proxSocket.Send(result, SocketFlags.None);
}
}
}
#endregion
#region 发送闪屏
private void btnSendShake_Click(object sender, EventArgs e)
{
foreach (var proxSocket in ClientProxSocketList)
{
if (proxSocket.Connected)
{
proxSocket.Send(new byte[] { 2 }, SocketFlags.None);
}
}
}
#endregion
}
}
c#Socket聊天程序客户端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
namespace SocketClient1
{
public partial class MainFrm : Form
{
public Socket ClientSocket { get; set; }
public MainFrm()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void btnStart_Click(object sender, EventArgs e)
{
//客户端连接服务器
//1.创建Socket对象
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ClientSocket = socket;
//2.连接服务器
//IPAddress ip = IPAddress.Any;
//IPEndPoint port = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//socket.Bind(port);
try
{
socket.Connect(IPAddress.Parse(txtIp.Text), int.Parse(txtPort.Text));
}
catch (Exception ex)
{
//MessageBox.Show(ex.ToString());
MessageBox.Show("重新 连接");
//Thread.Sleep(500);
//btnStart_Click(this, e);
return;
}
//发送消息,接受消息
Thread thread = new Thread(new ParameterizedThreadStart(ReceiveData));
thread.IsBackground = true;
thread.Start(ClientSocket);
}
#region 客户端接收数据
public void ReceiveData(object socket)
{
var proxSocket = socket as Socket;
byte[] data = new byte[1024 * 1024];
while (true)
{
int len = 0;
try
{
len = proxSocket.Receive(data, 0, data.Length, SocketFlags.None);
}
catch (Exception ex)
{
//异常退出
AppendTextToTxtlog(string.Format("服务器端:{0}非正常退出", proxSocket.RemoteEndPoint.ToString()));
StopContnet();//关闭连接
return;
}
if (len <= 0)
{
//客户端正常退出
AppendTextToTxtlog(string.Format("服务器端:{0}正常退出", proxSocket.RemoteEndPoint.ToString()));
StopContnet();//停止连接
return;//让方法结束,终结当前接收客户端数据异步线程
}
//把接收的数据放到文本框上去
//接收的数据中第一个字节如果是1:那么是字符串,如果是2是闪屏。如果是3是文件
#region 接收字符串
if (data[0] == 1)
{
string strMsg = ProcessRecieveString(data);
AppendTextToTxtlog(string.Format("接收到服务器端:{0}的消息是:{1}", proxSocket.RemoteEndPoint.ToString(), strMsg));
}
#endregion
#region 接收闪屏···
else if (data[0] == 2)
{
Shake();
}
#endregion
#region 接收的是文件
else if (data[0] == 3)
{
ProcessRecieveFile(data, len);
}
#endregion
}
}
#region 处理接收的文件
public void ProcessRecieveFile(byte[] data, int len)
{
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.DefaultExt = "txt";//默认后缀
sfd.Filter = "文本文件(*.txt)|*.txt|所有文件(*.*)|*.*";//保存类型
if (sfd.ShowDialog(this) != DialogResult.OK)
{
return;
}
byte[] fileData = new byte[len - 1];
Buffer.BlockCopy(data, 1, fileData, 0, len - 1);
File.WriteAllBytes(sfd.FileName, fileData);
}
}
#endregion
#region 屏幕晃动一下
public void Shake()
{
//把窗体最原始的坐标记住
Point oldLocation = this.Location;
Random r = new Random();
for (int i = 0; i < 50; i++)
{
this.Location = new Point(r.Next(oldLocation.X - 5, oldLocation.X + 5), r.Next(oldLocation.Y - 5, oldLocation.Y + 5));
Thread.Sleep(50);
this.Location = oldLocation;
}
}
#endregion
#endregion
#region 处理接收到的字符串
public string ProcessRecieveString(byte[] data)
{
//把实际的字符串拿到
string str = Encoding.Default.GetString(data, 1, data.Length - 1);
return str;
}
#endregion
public void StopContnet()
{
try
{
if (ClientSocket.Connected)
{
ClientSocket.Shutdown(SocketShutdown.Both);
ClientSocket.Close(100);
}
}
catch (Exception ex)
{
}
}
public void AppendTextToTxtlog(string txt)
{
if (txtlog.InvokeRequired)
{
txtlog.BeginInvoke(new Action<string>(s =>
{
this.txtlog.Text = string.Format("{0}\r\n{1}", txt, txtlog.Text);
}), txt);
//同步方法
txtlog.Invoke(new Action<string>(s =>
{
this.txtlog.Text = string.Format("{0}\r\n{1}", txt, txtlog.Text);
}), txt);
}
else
{
this.txtlog.Text = string.Format("{0}\r\n{1}", txt, txtlog.Text);
}
}
private void btnSendMsg_Click(object sender, EventArgs e)
{
if (ClientSocket.Connected)
{
byte[] data = Encoding.Default.GetBytes(txtMsg.Text);
ClientSocket.Send(data, 0, data.Length, SocketFlags.None);
}
}
private void MainFrm_FormClosing(object sender, FormClosingEventArgs e)
{
//判断是否已连接,如果连接那么就关闭连接
StopContnet();
}
}
}