首先这是服务器端的页面
#region 监听ip地址设置(服务器访问客户端ip地址设置,获取客户端ip地址个端口号)
private void btnStart_Click(object sender, EventArgs e)
{
if (txtIp.Text.Equals("")||txtPort.Text.Equals(""))//判断是否输入了ip地址和端口号
{
MessageBox.Show("请输入ip地址和端口号", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
try
{
//当点击开始监听的时候 在服务器端创建一个负责监听IP地址和端口号的Socket
//addressFamily: Socket:使用的寻址方案,socketType:Socket 的类型,protocolType:Socket 使用的协议。
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Any;
//创建服务器端网络端点对象
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//侦听Soket与本地终结点绑定
socketWatch.Bind(point);
//设置为监听状态
socketWatch.Listen(10);
ShowMsg("监听成功");
//新建线程等待连接,创建通信Socket
Thread th = new Thread(Listen);
th.IsBackground = true;//设置为后台线程
th.Start(socketWatch);
}
catch { }
}
}
Socket socketSend;
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
private void Listen(object o)
{
Socket socketWatch = o as Socket;
//循环目的在于使得多个客户端可以连接服务器
while (true)
{
try
{
//等待客户端连接,由侦听的Socket创建一个负责与客户端通信的Socket
socketSend = socketWatch.Accept();
//将远程连接的客户端的IP地址和Socket存入集合中
dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
//将远程连接的客户端的IP地址和端口号存入下拉框中
cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());
ShowMsg(socketSend.RemoteEndPoint.ToString() + ";" + "连接成功");//获取远程的客户端ip和端口
//创建新线程不停的接受客户端发过来的消息
Thread th = new Thread(Receive);
th.IsBackground = true;
th.Start(socketSend);
}
catch{ }
}
}
/// <summary>
/// 服务器端不停地接受客户端发来的消息
/// </summary>
/// <param name="o"></param>
private void Receive(object o)
{
Socket socketSend = o as Socket;
while (true)
{
try
{
//客户端连接成功后接受客户端发来的消息
byte[] buf = new byte[1024 * 1024 * 2];
int r = socketSend.Receive(buf);//实时接收的字节数
//如果客户端关闭发送有效字节数为0
if (r==0)
{
break;
}
ShowMsg(socketSend.RemoteEndPoint.ToString() + ";" + Encoding.UTF8.GetString(buf, 0, r));
}
catch{ }
}
}
private void ShowMsg(string str)
{
txtLog.AppendText(str + "\r\n");
}
#endregion
#region 服务器向客户端发送文本信息
private void btnSendMessage_Click(object sender, EventArgs e)
{
if (cboUsers.Text.Equals(""))//判断是否选择了客户端ip地址
{
MessageBox.Show("请选择客户端ip地址", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
if (txtMessage.Text.Equals(""))//判断是否输入了要发送的消息
{
MessageBox.Show("请输入要发送的信息", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
string str = txtMessage.Text.Trim();
byte[] buf = Encoding.UTF8.GetBytes(str);
List<byte> byteList = new List<byte>();
//根据自定义的协议,发送的字节数组的第一位为0是表示发送的是文本
byteList.Add(0);
byteList.AddRange(buf);
//泛型集合转换为新的数组
byte[] newBuffer = byteList.ToArray();
//获取用户在下拉框里面的ip地址
try
{
string ip = cboUsers.SelectedItem.ToString();
dicSocket[ip].Send(newBuffer);
}
catch { }
txtMessage.Text = null;
}
}
}
#endregion
#region 服务器向客户端发送文件
/// <summary>
/// 选择文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnChoose_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "请选择您要发送的文件";
ofd.InitialDirectory = @"C:\Users\Public\Pictures\Sample Pictures";
ofd.Filter = "所有文件|*.*";
ofd.ShowDialog();
//把文件路径显示在路径文本框
txtFilePath.Text = ofd.FileName;
}
/// <summary>
/// 发送文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSendFiles_Click(object sender, EventArgs e)
{
if (cboUsers.Text.Equals(""))//判断是否选择了客户端ip地址
{
MessageBox.Show("请选择客户端ip地址", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
if (txtFilePath.Text.Equals(""))//判读是否选择了文件路径
{
MessageBox.Show("请选择文件路径", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
//获取发送文件的路径
string path = txtFilePath.Text;
using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] buf = new byte[5 * 1024 * 1024];
int r = fsRead.Read(buf, 0, buf.Length);
List<byte> list = new List<byte>();
list.Add(1);
list.AddRange(buf);
byte[] newBuffer = list.ToArray();
//发送字节数组给指定客户端
dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer, 0, r + 1, SocketFlags.None);
}
}
}
}
#endregion
#region 服务器向客户端发送震动
/// <summary>
/// 服务器向客户端发送震动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSnake_Click(object sender, EventArgs e)
{
if (cboUsers.Text.Equals(""))//判断是否选择了客户端ip地址
{
MessageBox.Show("请选择客户端ip地址", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
byte[] buffer = new byte[1];
buffer[0] = 2;
dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer);
}
}
#endregion
#region 鼠标点击清除提示文字
/// <summary>
/// 鼠标点击清除提示文字
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void txtMessage_mouseDown(object sender, MouseEventArgs e)
{
this.txtMessage.Text = "";
}
#endregion
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;//取消跨线程检测
Form2 f2 = new Form2();
f2.Show();
}
这是客户端的页面
//创建负责通信的socket
Socket sendSocket;
#region 接收服务器端发来的消息
private void btnStart_Click(object sender, EventArgs e)
{
if (txtIp.Text.Equals("") || txtPort.Text.Equals(""))//判读是否输入了ip地址和端口号
{
MessageBox.Show("请输入ip地址和端口号", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
try
{
sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(txtIp.Text);
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//获取远程服务器的ip地址和端口号
sendSocket.Connect(point);
ShowMsg("连接成功");
//开启一个新的线程不停的接受服务器发来的消息
Thread th = new Thread(Receive);
th.IsBackground = true;
th.Start();
}
catch
{
}
}
}
/// <summary>
/// 不停接收服务器发来的消息
/// </summary>
private void Receive()
{
while (true)
{
try
{
byte[] buffer = new byte[1024 * 1024 * 3];
int r = sendSocket.Receive(buffer);//实时接收有效字节数
if (r==0)
{
break;
}
//接收的是文字消息
if (buffer[0]==0)
{
string str = Encoding.UTF8.GetString(buffer, 1, r - 1);//从下标为1的开始解析r-1个
ShowMsg(sendSocket.RemoteEndPoint + ";" + str);
}
//接收的是文件
else if (buffer[0]==1)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Title = "请选择保持路径";
sfd.InitialDirectory = @"C:\Users\Public\Pictures\Sample Pictures";
sfd.Filter = "所有文件|*.*";
sfd.ShowDialog(this);
string path = sfd.FileName;
using (FileStream fsWrite = new FileStream(path,FileMode.Open,FileAccess.Write))
{
fsWrite.Write(buffer, 1, r - 1);
}
MessageBox.Show("保存成功");
}
//震动接收
else if (buffer[0]==2)
{
shake();
}
}
catch
{
}
}
}
/// <summary>
/// 震动方法
/// </summary>
private void shake()
{
for (int i = 0; i < 500; i++)
{
this.Location = new Point(200, 300);
this.Location = new Point(300, 300);
}
}
private void ShowMsg(string str)
{
txtLog.AppendText(str + "\r\n");
}
#endregion
#region 向服务器发送消息
/// <summary>
/// 向服务器发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSendMessage_Click(object sender, EventArgs e)
{
if (txtMessage.Text.Equals(""))//判读是否填写发送消息
{
MessageBox.Show("请输入要发送的信息", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
string str = txtMessage.Text.Trim();
byte[] buf = Encoding.UTF8.GetBytes(str);
//发送消息
sendSocket.Send(buf);
txtMessage.Text = null;
}
}
#endregion
#region 鼠标点击清除提示文字
/// <summary>
/// 鼠标点击清除提示文字
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void txtMessage_mouseDown(object sender, MouseEventArgs e)
{
this.txtMessage.Text = "";
}
#endregion
private void Form2_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;//取消跨线程检查
}
下面是执行顺序
1.首先在服务器端输入ip地址以及端口号,点击开始监听,
然后在客户端输入相应的ip地址以及端口号,点击连接。(通过如图)
2.在服务器端的下拉选择框选择客户端ip地址与端口号(注意如果不选择,发送消息,震动以及发送文件功能无法实现,如图)
一下的操作就简单了,客户端可以向服务器端发送消息,服务器端也能向客户端发送相应的动作(如图)