自己定制一个协议
Server:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
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 _123_服务器与客户端交互_聊天_Server
{
public partial class FormServer : Form
{
public FormServer()
{
InitializeComponent();
}
/// <summary>
/// 点击按钮开始监听
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, EventArgs e)
{
try
{
//创建一个负责监听(服务器IP地址和端口号)的Socket // 网络协议IP V4版本 流式使用TCP协议
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//创建IP地址和端口号对象
IPAddress ip = IPAddress.Any; //客户端的活动地址,可变 //IPAddress.Parse(txtServer.Text);这样子只会把txtServer.Text作为IP地址不可变。
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//让负责监听的Socket绑定IP地址和端口号
socketWatch.Bind(point);
ShowMsg("监听成功");
//设置监听队列
socketWatch.Listen(10);//在某一时间点内最大容量
Thread th = new Thread(Listen);
th.IsBackground = true;
th.Start(socketWatch);
}
catch
{
MessageBox.Show("Server项目的(btnStart_Click())可能出问题了,请找大师。");
}
}
/// <summary>
/// 将字符串显示在Log文本框中
/// </summary>
/// <param name="str">即将要显示的字符串</param>
public void ShowMsg(string str)
{
txtLog.AppendText(str + "\r\n");
}
//将远程连接的客户端IP地址和Socket存入集合中
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
//创建跟客户端通信的Socket类的变量
Socket socketSend;
/// <summary>
/// 等待客户端的连接,并且创建与之通信的Socket
/// </summary>
public void Listen(object o)
{
Socket socketWatch = o as Socket;
while (true)
{
try
{
//负责监听的Socket 来接受客户端的连接(等待客户端连接) 并且创建跟客户端通信的Socket
//负责和客户端通信的Socket
socketSend = socketWatch.Accept();
//将此时客户端ip和SocketSend存入
dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
//将此时客户端的ip地址和端口号存入下拉框中
cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());
//将谁(远程终结点)连接显示在文本框内
ShowMsg(socketSend.RemoteEndPoint.ToString() + ":连接成功");//获取远程终结点
//开启一个新线程,不停地接受客户端发来的消息
Thread th = new Thread(Receive);
th.IsBackground = true;
th.Start(socketSend);
}
catch
{
MessageBox.Show("Server项目的(Listen())可能出问题了,请找大师。");
}
}
}
/// <summary>
/// 服务器端不停地接受客户端发来的消息
/// </summary>
/// <param name="o"></param>
public void Receive(object o)
{
Socket socketSend = o as Socket;
while (true)
{
try
{
//客户端连接成功后,服务器应该接受客户端发来的消息
byte[] buffer = new byte[1024 * 1024 * 2];
//实际接收到的有限字节数
int r = socketSend.Receive(buffer);
if (r == 0)
{
break;
}
string input = Encoding.UTF8.GetString(buffer, 0, r);
//显示客户端发送的数据
ShowMsg(DateTime.Now + "\r\n" + socketSend.RemoteEndPoint + ":" + input);
}
catch
{
//
MessageBox.Show("Server项目的(Receive())可能出问题了,请找大师。");
}
}
}
/// <summary>
/// 取消不可跨线程访问
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormServer_Load(object sender, EventArgs e)
{
//取消不可跨线程访问
Control.CheckForIllegalCrossThreadCalls = false;
}
private void FormServer_DoubleClick(object sender, EventArgs e)
{
////当你点击关闭窗口的时候,判断线程是否为null
//if (th != null)
//{
// //th.Abort();//线程被Abort后就不能被Start了
// th = null;
//}
}
/// <summary>
/// 服务器给客户端发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
string input = txtMsg.Text.Trim();
byte[] buffer = Encoding.UTF8.GetBytes(input);
//制定协议 字节数组第一位为0:文本消息 1:文件 2:震动
List<byte> list = new List<byte>();
list.Add(0);//给第一位赋值为0
list.AddRange(buffer);
//将泛型集合穿换成数组
byte[] newBuffer = list.ToArray(); //buffer = list.ToArray();不可以 数组长度不一样了
//获得用户在下拉框中选中的IP地址
string ip = cboUsers.SelectedItem.ToString();
dicSocket[ip].Send(newBuffer);
//socketSend.Send(buffer);
//发送成功后清除当前文本
txtMsg.Clear();
txtMsg.Focus();
}
private void btnSelect_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "客官,请选择你要发送的文件";
ofd.InitialDirectory = @"C:\Users\46124\Desktop";
ofd.Filter = "文本文件|*.txt|媒体文件|*.wav|媒体文件|*.mp4|所有文件|*.*";
ofd.ShowDialog();
//将对话框选择的文件的全路径放入文本框中
txtPath.Text = ofd.FileName;
}
/// <summary>
/// 点击发送文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSendFile_Click(object sender, EventArgs e)
{
//获得要发送文件的路径
string path = txtPath.Text;
using (FileStream fsRead = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read))
{
byte[] buffer = new byte[1024 * 1024 * 5];
int r = fsRead.Read(buffer, 0, buffer.Length);
//制定协议 字节数组第一位为0:文本消息 1:文件 2:震动
List<byte> list = new List<byte>();
list.Add(1);
list.AddRange(buffer);
byte[] newBuffer = list.ToArray();
//通过下拉框获取需要发送客户端的IP然后发送字节数组
dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer);
MessageBox.Show("发送成功");
}
}
/// <summary>
/// 发送振动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnVibrate_Click(object sender, EventArgs e)
{
byte[] buffer = new byte[1];
buffer[0] = 2;
//通过下拉框获取需要发送客户端的IP然后发送字节数组
dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer);
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
Client:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
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 _124_服务器与客户端交互_聊天_Client
{
public partial class FormClient : Form
{
public FormClient()
{
InitializeComponent();
}
Socket socketSend;
private void button1_Click(object sender, EventArgs e)
{
try
{
//创建负责通信的Socket
socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//创建IP和端口号连接服务器
IPAddress ip = IPAddress.Parse(txtServer.Text);
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//获得要连接的远程服务器应用程序的IP地址和端口号
socketSend.Connect(point);
ShowMsg("连接成功");
//开启一个新的线程不停地接受服务器发送来的消息
Thread th = new Thread(Receive);
th.IsBackground = true;
th.Start();
}
catch
{
MessageBox.Show("连接服务器时出错,请找大师");
}
}
/// <summary>
/// 将字符串显示在Log文本框中
/// </summary>
/// <param name="str">即将要显示的字符串</param>
public void ShowMsg(string str)
{
txtLog.AppendText(str + "\r\n");
}
/// <summary>
/// 客户端给服务器发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
//将客户端发送的数据string转化成byte发送
string input = txtMsg.Text.Trim();
byte[] buffer = Encoding.UTF8.GetBytes(input);
socketSend.Send(buffer);
//发送成功后清除当前文本
txtMsg.Clear();
txtMsg.Focus();
}
/// <summary>
/// 不停的接受服务器发来的消息
/// </summary>
public void Receive()
{
try
{
while (true)
{
byte[] buffer = new byte[1024 * 1024 * 2];
int r = socketSend.Receive(buffer);
if (r == 0)
{
break;
}
//使用协议判断字节数组第一位 0:文本消息 1:文件 2:震动
if (buffer[0] == 0)
{
string input = Encoding.UTF8.GetString(buffer, 1, r - 1); //r-1是因为数组加了一位 数量多了一个
ShowMsg(DateTime.Now + "\r\n" + socketSend.RemoteEndPoint + ":" + input);
}
else if (buffer[0] == 1)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = @"C:\Users\46124\Desktop";
sfd.Title = "客官,请选择保存文件的地址";
sfd.Filter = "文本文件|*.txt|媒体文件|*.wav|媒体文件|*.mp4|所有文件|*.*";
sfd.ShowDialog(this);
string path = sfd.FileName;
using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
fsWrite.Write(buffer, 1, r - 1);
MessageBox.Show("接受成功");
}
}
else if (buffer[0] == 2)
{
Vibrate();
}
}
}
catch
{
MessageBox.Show("(Client项目的Receive())可能出问题了,请找大师。");
}
}
private void FormClient_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// 振动
/// </summary>
public void Vibrate()
{
for (int i = 0; i < 2000; i++)
{
//Random r = new Random();
//int rNumber = r.Next(100, 250);
//this.Location = new Point(this.Location.X + rNumber, this.Location.Y + rNumber);
this.Location = new Point(200, 200);
this.Location = new Point(300, 300);
}
}
}
}