服务端
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;
using System.IO;
namespace 我的聊天程序
{
public partial class serverForm : Form
{
public serverForm()
{
InitializeComponent();
}
Socket acceptUser;//连接客户端的socket实例
Dictionary<string,Socket> userList = new Dictionary<string, Socket>();
bool[] messType = { true, false, false };//默认用户要发送文字消息 [0]:发文字消息 [1]:发文件 [2]:发抖动窗口消息
string sendFilePath;
string fileName;
/// <summary>
/// 开始监听
/// 1.创建socket对象
/// 2.绑定IP和端口
/// 3.设置监听队列
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void startListen_Click(object sender, EventArgs e)
{
//1.创建socket对象
//参数1: 寻址方案:IP 4版本
//参数2: 数据传输方式 以流的方式传输
//参数3: 数据传输协议 TCP协议
Socket serveSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//2.绑定IP和端口
try
{
IPAddress severIP = IPAddress.Parse(showIPAdd.Text.ToString());
IPEndPoint ipAndPor = new IPEndPoint(severIP, Convert.ToInt32(showPort.Text));
serveSocket.Bind(ipAndPor);
//3.设置监听队列
serveSocket.Listen(10);
loadSever();
//开辟一个线程去等待用户连接
Thread waitUserAccpet = new Thread(listen);
waitUserAccpet.IsBackground = true;
waitUserAccpet.Start(serveSocket);
sendFile.Enabled = true;
accepUsertList.Enabled = true;
sendShake.Enabled = true;
serveMessEdit.Enabled = true;
serveSendMess.Enabled = true;
startListen.Enabled = false;
}
catch
{
serveShowMessge("IP地址或端口无效,请确认无误后在重试");
}
}
/// <summary>
/// 显示整个过程需要显示的文本
/// </summary>
/// <param name="showMess"></param>
private void serveShowMessge(string showMess)
{
showSeverLog.AppendText(showMess+"\r\n");
}
/// <summary>
/// 因为不能让主线程去一直等待用户连接
/// 新建一个线程专门负责去等待用户连接
/// </summary>
/// <param name="serveSock"></param>
private void listen(object o)
{
Socket serveSocketMes = o as Socket;
while (true)
{
try
{
acceptUser = serveSocketMes.Accept();
serveShowMessge(acceptUser.RemoteEndPoint.ToString() + ":\t" + "连接成功");
userList.Add(acceptUser.RemoteEndPoint.ToString(), acceptUser);
accepUsertList.Items.Add(acceptUser.RemoteEndPoint.ToString());
Thread recevieUseerMes = new Thread(recevie);
recevieUseerMes.IsBackground = true;
recevieUseerMes.Start();
}
catch
{
}
}
}
/// <summary>
/// 程序加载时显示字符
/// </summary>
private void loadSever()
{
serveShowMessge("服务已启动");
Thread.Sleep(1000);
serveShowMessge("正在开启监听");
Thread.Sleep(1000);
serveShowMessge("监听成功等待用户连接");
}
/// <summary>
/// 取消对跨线程访问的限制
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void serverForm_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// 接收客户端发送的消息
/// </summary>
/// <param name="serverSocke"></param>
private void recevie()
{
byte[] recevieMessBuf = new byte[1024 * 1024 * 5];
while (true)
{
try
{
int recevieCountBy = acceptUser.Receive(recevieMessBuf);
if (recevieCountBy == 0)
{
serveShowMessge("对方可能已经下线了");
break;
}
MessageHandle(recevieMessBuf, recevieCountBy);
}
catch { }
}
}
/// <summary>
/// 给客户端发消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void serveSendMess_Click(object sender, EventArgs e)
{
SendMessHandle();
messType[0] = true;
messType[1] = false;
messType[2] = false;
}
/// <summary>
/// 发送消息处理
/// </summary>
private void SendMessHandle()
{
List<byte> messByte = new List<byte>();
if (messType[0])
{
try
{
messByte.Add(0);
messByte.AddRange(Encoding.Default.GetBytes(serveMessEdit.Text));
byte[] sendMessBuffer = messByte.ToArray();
userList[accepUsertList.SelectedItem.ToString()].Send(sendMessBuffer);
serveShowMessge("自己:" + serveMessEdit.Text);
serveMessEdit.Clear();
}
catch { }
}
else if (messType[1])
{
try
{
//1.先发送文件名
messByte.Add(1);
messByte.AddRange(Encoding.Default.GetBytes(Path.GetFileName(sendFilePath)));
byte[] sendMessBuffer = messByte.ToArray();
userList[accepUsertList.SelectedItem.ToString()].Send(sendMessBuffer);
serveShowMessge("自己:" + Path.GetFileName(sendFilePath));
messByte.Clear();
//2.正式发送文件
messByte.Add(2);
using (FileStream readSendFile = new FileStream(sendFilePath, FileMode.Open, FileAccess.Read))
{
byte[] fileBuffer = new byte[1024 * 1024 * 4];
int readByCount = readSendFile.Read(fileBuffer, 0, fileBuffer.Length);
messByte.AddRange(fileBuffer);
messByte.RemoveRange(readByCount + 1, messByte.Count - readByCount - 1);
sendMessBuffer = messByte.ToArray();
userList[accepUsertList.SelectedItem.ToString()].Send(sendMessBuffer);
}
}
catch { }
}
else
{
try
{
byte[] buffer = { 3 };
userList[accepUsertList.SelectedItem.ToString()].Send(buffer);
serveShowMessge("自己:\t给对方发了一个窗口抖动消息");
}
catch { }
}
}
/// <summary>
/// 用户需要发送文件
/// 确定用户选择了文件后,传递用户选择的文件名
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void sendFile_Click(object sender, EventArgs e)
{
OpenFileDialog selectSendFile = new OpenFileDialog();
selectSendFile.Title = "选择你要发送的文件";
selectSendFile.Filter = "文本文件|*.txt|所有文件|*.*";
selectSendFile.Multiselect = false;
selectSendFile.ShowDialog();
sendFilePath = selectSendFile.FileName;
if (sendFilePath != "")
{
messType[0] = false;
messType[1] = true;
messType[2] = false;
}
}
/// <summary>
/// 消息有很多类,所以根据缓冲字节数组的第一位鉴别是哪类消息
/// [0]=0 代表接收的是文字消息
/// [0]=1 代表接收的文件名消息
/// [0]=2 代表接收到用文件的字节
/// [0]=3 代表接收的时抖动窗口消息
/// </summary>
/// <param name="mesBuffer">接收其他用户发送的字节数组 </param>
/// <param name="count">实际接收的字节个数</param>
private void MessageHandle(byte[] mesBuffer,int count)
{
try
{
if (mesBuffer[0] == 0)
{
string textMes = Encoding.Default.GetString(mesBuffer, 1, count - 1);
serveShowMessge(acceptUser.RemoteEndPoint.ToString() + ":\t" + textMes);
}
else if (mesBuffer[0] == 1)
{
fileName = Encoding.Default.GetString(mesBuffer, 1, count - 1);
serveShowMessge(acceptUser.RemoteEndPoint.ToString() + ":\t" + fileName);
}
else if (mesBuffer[0] == 2)
{
string fileFullPath = @"C:\Users\Administrator\Desktop\";
fileFullPath += fileName;
using (FileStream writeRecivevFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write))
{
writeRecivevFile.Write(mesBuffer, 1, count - 1);
}
serveShowMessge(fileName + "接收成功");
fileName = null;
}
else
{
formShake();
serveShowMessge(acceptUser.RemoteEndPoint.ToString() + ":\t" + "给你发了一个窗口抖动");
}
}
catch { }
}
/// <summary>
/// 抖动窗口
/// </summary>
private void formShake()
{
for (int i = 0; i < 500; i++)
{
this.Location = new Point(25, 100);
this.Location = new Point(30, 100);
}
}
/// <summary>
/// 窗口抖动消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void sendShake_Click(object sender, EventArgs e)
{
messType[0] = false;
messType[1] = false;
messType[2] = true;
}
}
}
客户端
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;
using System.Threading;
using System.IO;
namespace 客户端
{
public partial class userForm : Form
{
public userForm()
{
InitializeComponent();
}
Socket userSocket;
string sendFilePath;
string fileName;
bool[] messType = { true, false, false };//默认用户要发送文字消息 [0]:发文字消息 [1]:发文件 [2]:发抖动窗口消息
/// <summary>
/// 客户端连接服务器
/// 1.创建一个socket对象
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void connectServe_Click(object sender, EventArgs e)
{
//1.创建一个socket对象
userSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//用域名绑定IP
//IPHostEntry hostInfo = Dns.GetHostEntry("19u232j797.51mypc.cn");
//IPAddress ipAddress = hostInfo.AddressList[0];
//2.连接服务器
IPAddress serverIP = IPAddress.Parse(showUserIP.Text);
userSocket.Connect(serverIP, Convert.ToInt32(showUserPort.Text));
showUserMessage("连接成功");
//启动发送消息的控件
sendFile.Enabled = true;
sendShakeMes.Enabled = true;
userMesEdit.Enabled = true;
userSendMes.Enabled = true;
//接受客户端发送的消息
Thread recevieServeMes = new Thread(recevie);
recevieServeMes.IsBackground = true;
recevieServeMes.Start();
connectServe.Enabled = false;
}
/// <summary>
/// 在整个过程中需要显示在消息日志上的字符
/// </summary>
/// <param name="userMessage"></param>
private void showUserMessage(string userMessage)
{
showUserLog.AppendText(userMessage+"\r\n");
}
/// <summary>
/// 接收服务端发送的消息
/// </summary>
private void recevie()
{
while (true)
{
try
{
byte[] receServMesBuf = new byte[1024 * 1024 * 5];
int recevieCountBy = userSocket.Receive(receServMesBuf);
MessageHandle(receServMesBuf, recevieCountBy);
}
catch { }
}
}
/// <summary>
/// 客户端给服务器发消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void userSendMes_Click(object sender, EventArgs e)
{
SendMessHandle();
messType[0] = true;
messType[1] = false;
messType[2] = false;
}
/// <summary>
/// 取消对跨线程的限制
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void userForm_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// 发送文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void sendFile_Click(object sender, EventArgs e)
{
OpenFileDialog selectSendFile = new OpenFileDialog();
selectSendFile.Title = "选择你要发送的文件";
selectSendFile.Filter = "文本文件|*.txt|所有文件|*.*";
selectSendFile.Multiselect = false;
selectSendFile.ShowDialog();
sendFilePath = selectSendFile.FileName;
if (sendFilePath != "")
{
messType[0] = false;
messType[1] = true;
messType[2] = false;
}
}
/// <summary>
/// 发送消息处理
/// </summary>
private void SendMessHandle()
{
List<byte> messByte = new List<byte>();
if (messType[0])
{
try
{
messByte.Add(0);
messByte.AddRange(Encoding.Default.GetBytes(userMesEdit.Text));
byte[] sendMessBuffer = messByte.ToArray();
userSocket.Send(sendMessBuffer);
showUserMessage("自己:" + userMesEdit.Text);
userMesEdit.Clear();
}
catch { }
}
else if (messType[1])
{
try
{
//1.先发送文件名
messByte.Add(1);
messByte.AddRange(Encoding.Default.GetBytes(Path.GetFileName(sendFilePath)));
byte[] sendMessBuffer = messByte.ToArray();
userSocket.Send(sendMessBuffer);
showUserMessage("自己:" + Path.GetFileName(sendFilePath));
messByte.Clear();
//2.正式发送文件
messByte.Add(2);
using (FileStream readSendFile = new FileStream(sendFilePath, FileMode.Open, FileAccess.Read))
{
byte[] fileBuffer = new byte[1024 * 1024 * 4];
int readByCount = readSendFile.Read(fileBuffer, 0, fileBuffer.Length);
messByte.AddRange(fileBuffer);
messByte.RemoveRange(readByCount + 1, messByte.Count - readByCount - 1);
sendMessBuffer = messByte.ToArray();
userSocket.Send(sendMessBuffer);
}
}
catch { }
}
else
{
try
{
byte[] buffer = { 3 };
userSocket.Send(buffer);
showUserMessage("自己:\t给对方发了一个窗口抖动消息");
}
catch { }
}
}
/// <summary>
/// 消息有很多类,所以根据缓冲字节数组的第一位鉴别是哪类消息
/// [0]=0 代表接收的是文字消息
/// [0]=1 代表接收的文件名消息
/// [0]=2 代表接收到用文件的字节
/// [0]=3 代表接收的时抖动窗口消息
/// </summary>
/// <param name="mesBuffer">接收其他用户发送的字节数组 </param>
/// <param name="count">实际接收的字节个数</param>
private void MessageHandle(byte[] mesBuffer, int count)
{
try
{
if (mesBuffer[0] == 0)
{
string textMes = Encoding.Default.GetString(mesBuffer, 1, count - 1);
showUserMessage(userSocket.RemoteEndPoint.ToString() + ":\t" + textMes);
}
else if (mesBuffer[0] == 1)
{
fileName = Encoding.Default.GetString(mesBuffer, 1, count - 1);
showUserMessage(userSocket.RemoteEndPoint.ToString() + ":\t" + fileName);
}
else if (mesBuffer[0] == 2)
{
string fileFullPath = @"C:\Users\Administrator\Desktop\";
fileFullPath += fileName;
using (FileStream writeRecivevFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write))
{
writeRecivevFile.Write(mesBuffer, 1, count - 1);
}
showUserMessage(fileName + "接收成功");
fileName = null;
}
else
{
formShake();
showUserMessage(userSocket.RemoteEndPoint.ToString() + ":\t" + "给你发了一个窗口抖动");
}
}
catch { }
}
/// <summary>
/// 抖动窗口
/// </summary>
private void formShake()
{
for (int i = 0; i < 500; i++)
{
this.Location = new Point(25, 100);
this.Location = new Point(30, 100);
}
}
private void sendShakeMes_Click(object sender, EventArgs e)
{
messType[0] = false;
messType[1] = false;
messType[2] = true;
}
}
}