创建winform窗体应用程序名字为Server服务端
首先用3个textBox控件设置文本和名字分别为(txtSever),(txtPort),(txtPath)
再用2个Richbox控件调整大小·,设置名字(richLog),(richMsg)
在用5个button按钮设置文本,设置名字(btnStart),(btnSelect),(btnSendFile),(btnSend),(btnZD)
在用一个Combox控件设置名字(cboUsers)
在创建客户端的winform窗体应用程序名字为Cilent客户端
使用2个textbox控件设置文本,设置名字(txtSever),(txtPort)
在使用2个richbox控件设置文本,设置名字(richLog),(richMsg)
在用2个按钮设置文本,设置名字(btnStart),(btnSend)
首先在开始监听的Click事件里,创建监听的Socket,创建IP地址和端口号,绑定端口号和设置监听队列,并写一个方法来显示信息
private void btnStart_Click(object sender, EventArgs e)
{
try //涉及网络连接都需要try起来
{
//创建监听的Socket
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//创建IP地址
IPAddress ip = IPAddress.Any; //IPAddress.Parse();
//创建端口号
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//先绑定IP地址和端口号
socketWatch.Bind(point);
//设置监听队列
socketWatch.Listen(10);
//显示监听成功
ShowMsg("监听成功");
/// <summary>
/// 显示信息
/// </summary>
/// <param name="str"></param>
public void ShowMsg(string str)
{
richLog.AppendText(str + "\r\n");
}
在创建一个方法通过Accept创建和客户端通信的Socket
//拿到了对应客户端IP地址跟客户端通信的Socket
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
//将通信的Socket设置全局Socket,方便其他方法调用
Socket socketSend;
/// <summary>
/// 服务端和客户端通信
/// </summary>
/// <param name="o"></param>
public void Listen(object o)
{
//把object类型转换成Socket
Socket socketWatch = o as Socket;
//这个方法要通过线程来执行
while (true)
{
try
{
//通过Accept这个方法创建负责和客户端通信的Socket
socketSend = socketWatch.Accept();
//将客户端的IP地址和端口号存储到Combox中下拉框中
cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());
//在将ip地址和IP地址对应的Socket添加到键值对集合里
dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
//把连接服务端的IP地址和端口号显示到richLog中
ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功");
//开启新线程执行Rec方法
Thread th2 = new Thread(Rec);
//设置后台线程
th2.IsBackground = true;
//标记这个线程可以被cpu执行了
th2.Start(socketSend);
}
catch
{
}
}
}
加载窗体时取消跨线程访问
/// <summary>
/// 加载窗体跨线程的访问
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
创建一个方法不停的接收客户端发来的信息
/// <summary>
/// 不停的接收客户端发来的消息
/// </summary>
/// <param name="o"></param>
public void Rec(object o)
{
Socket socketSend = o as Socket;
while (true)
{
try
{
//服务端开始接收客户端发来的数据
byte[] buffer = new byte[1024 * 1024 * 5];
//实际接收到的有效字节数
int r = socketSend.Receive(buffer);
//客户端下线了
if (r == 0)
{
break;
}
//将字节数组转换成字符串
string str = System.Text.Encoding.UTF8.GetString(buffer, 0, r);
ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + str);
}
catch
{
}
}
}
服务端给客户端发送文字消息
/// <summary>
/// 服务端给客户端发送文字消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
//拿到服务端发送的信息转换成字节数组
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(richMsg.Text);
//先创建一个byte泛型集合
List<byte> list = new List<byte>();
//集合里面存储 0-文字
list.Add(0);
//集合存储字节数组
list.AddRange(buffer);
//将集合转换成字节数组
byte[] newBuffer = list.ToArray(); //要转换的类型取决于什么类型的泛型集合
//获得在下拉框中选中的IP地址
string ip = cboUsers.SelectedItem.ToString();
//把信息发送给客户端
dicSocket[ip].Send(newBuffer);
}
服务端发送文件
/// <summary>
/// 服务端选择文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSelect_Click(object sender, EventArgs e)
{
//创建打开对话框
OpenFileDialog ofd = new OpenFileDialog();
//设置菜单条
ofd.Title = "请选择要发送的文件";
//设置初始目录
ofd.InitialDirectory = @"C:\Users\Administrator\Desktop";
//设置文件类型
ofd.Filter = "文本文件|*.txt|音乐文件|*.wav|图片文件|*.jpg|所有文件|*.*";
//运行对话框
ofd.ShowDialog(this);
//获得用户选择的文件路径
string path = ofd.FileName;
//把用户选中的文件路径显示到textbox中
txtPath.Text = path;
}
向客户端发送文件
/// <summary>
/// 向客户端发送文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSendFile_Click(object sender, EventArgs e)
{
using (FileStream fsRead = new FileStream(txtPath.Text, FileMode.OpenOrCreate, FileAccess.Read))
{
//声明一个字节数组,拿到文件的长度就是文件的大小
byte[] buffer = new byte[fsRead.Length];
//实际读取到的有效字节数
int r = fsRead.Read(buffer, 0, buffer.Length);
//声明byte类型的泛型集合
List<byte> list = new List<byte>();
//在集合里存储1-文件
list.Add(1);
list.AddRange(buffer);
byte[] newBuffer = list.ToArray();
//先获得用户选择的IP地址
string ip = cboUsers.SelectedItem.ToString();
//因为发送文件拿不到实际读取的有效字节数,所以要拿到文件的长度
dicSocket[ip].Send(newBuffer);
}
}
服务端给客户端发送震动
/// <summary>
/// 服务端给客户端发送震动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnZD_Click(object sender, EventArgs e)
{
//这个字节数组里只有一个字节
byte[] buffer = new byte[1];
//索引第一个字节赋值为2-震动
buffer[0] = 2;
//拿到选择的客户端
string ip = cboUsers.SelectedItem.ToString();
//拿到客户端发送字节数组
dicSocket[ip].Send(buffer);
}
接下来是客户端的代码
首先连接服务端,创建负责和客户端通信的Socket
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 Client客户练习
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//设置全局通信Socket让其他方法可以调用
Socket socketSend;
/// <summary>
/// 客户端连接服务端
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, EventArgs e)
{
try
{
//在客户端创建一个负责跟客户端通信的Socket
socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//获得要连接的服务端的IP地址
IPAddress ip = IPAddress.Parse(txtSever.Text);
//获得要连接的服务端端口号
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//客户端负责通信的Socket去连接服务端的ip地址和端口号
socketSend.Connect(point);
ShowMsg("连接成功");
//创建新线程执行Rec方法
Thread th1 = new Thread(Rec);
//设置后台线程
th1.IsBackground = true;
//标记这个线程可以被cpu执行了
th1.Start();
}
catch
{
}
}
在创建一个方法用来显示服务端的信息
/// <summary>
/// 显示服务端的信息
/// </summary>
/// <param name="str"></param>
public void ShowMsg(string str)
{
richLog.AppendText(str + "\r\n");
}
创建一个方法用来接收服务端的数据
/// <summary>
/// 客户端接收服务端发来的数据
/// </summary>
public void Rec()
{
while (true)
{
try
{
//客户端接收服务端发来的数据
byte[] buffer = new byte[1024 * 1024 * 5];
//实际接收的有效字节数
int r = socketSend.Receive(buffer);
//从字节数组第一位索引开始
byte b = buffer[0];
//接收的是文字
if(b==0)
{
//从字节数组索引第二位开始解码
string str = System.Text.Encoding.UTF8.GetString(buffer, 1, r-1);
ShowMsg(str);
}
//接收的是文件
else if(b==1)
{
//保存对话框
SaveFileDialog sfd = new SaveFileDialog();
//设置菜单条
sfd.Title = "请选择要保存的文件路径";
//设置初始路径
sfd.InitialDirectory = @"C:\Users\Administrator\Desktop";
//设置文件类型
sfd.Filter = "文本文件|*.txt|音乐文件|*.wav|图片文件|*.jpg|所有文件|*.*";
//运行保存对话框
sfd.ShowDialog(this); //win7或win8需要加this是个bug
string path = sfd.FileName;
using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
//从字节数组第二位索引开始,每次实际接收的有效字节数-1
fsWrite.Write(buffer,1, r - 1);
}
MessageBox.Show("保存成功");
}
//接收的是震动
else if(b==2)
{
ZD();
}
}
catch
{
}
}
}
窗体加载的时候取消跨线程的访问
/// <summary>
/// 取消客户端跨线程的访问
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
客户端给服务端发送信息
/// <summary>
/// 客户端给服务端发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
//先拿到要发送的消息
string str = richMsg.Text;
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
socketSend.Send(buffer);
}
写一个方法用来客户端震动
/// <summary>
/// 让客户端震动
/// </summary>
public void ZD()
{
for (int i = 0; i < 200; i++)
{
this.Location = new Point(220, 220);
this.Location = new Point(420, 420);
}
}
以下是服务端和客户端全部代码
服务端:
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 Server服务练习2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
try //涉及网络连接都需要try起来
{
//创建监听的Socket
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//创建IP地址
IPAddress ip = IPAddress.Any; //IPAddress.Parse();
//创建端口号
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//先绑定IP地址和端口号
socketWatch.Bind(point);
//设置监听队列
socketWatch.Listen(10);
//显示监听成功
ShowMsg("监听成功");
//开启新线程来执行Listen方法
Thread th1 = new Thread(Listen);
//设置后台线程
th1.IsBackground = true;
//标记这个线程可以被cpu执行了
th1.Start(socketWatch);
}
catch
{
}
}
/// <summary>
/// 显示信息
/// </summary>
/// <param name="str"></param>
public void ShowMsg(string str)
{
richLog.AppendText(str + "\r\n");
}
//拿到了对应客户端IP地址跟客户端通信的Socket
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
//将通信的Socket设置全局Socket,方便其他方法调用
Socket socketSend;
/// <summary>
/// 服务端和客户端通信
/// </summary>
/// <param name="o"></param>
public void Listen(object o)
{
//把object类型转换成Socket
Socket socketWatch = o as Socket;
//这个方法要通过线程来执行
while (true)
{
try
{
//通过Accept这个方法创建负责和客户端通信的Socket
socketSend = socketWatch.Accept();
//将客户端的IP地址和端口号存储到Combox中下拉框中
cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());
//在将ip地址和IP地址对应的Socket添加到键值对集合里
dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
//把连接服务端的IP地址和端口号显示到richLog中
ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功");
//开启新线程执行Rec方法
Thread th2 = new Thread(Rec);
//设置后台线程
th2.IsBackground = true;
//标记这个线程可以被cpu执行了
th2.Start(socketSend);
}
catch
{
}
}
}
/// <summary>
/// 加载窗体跨线程的访问
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// 不停的接收客户端发来的消息
/// </summary>
/// <param name="o"></param>
public void Rec(object o)
{
Socket socketSend = o as Socket;
while (true)
{
try
{
//服务端开始接收客户端发来的数据
byte[] buffer = new byte[1024 * 1024 * 5];
//实际接收到的有效字节数
int r = socketSend.Receive(buffer);
//客户端下线了
if (r == 0)
{
break;
}
//将字节数组转换成字符串
string str = System.Text.Encoding.UTF8.GetString(buffer, 0, r);
ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + str);
}
catch
{
}
}
}
/// <summary>
/// 服务端给客户端发送文字消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
//拿到服务端发送的信息转换成字节数组
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(richMsg.Text);
//先创建一个byte泛型集合
List<byte> list = new List<byte>();
//集合里面存储 0-文字
list.Add(0);
//集合存储字节数组
list.AddRange(buffer);
//将集合转换成字节数组
byte[] newBuffer = list.ToArray(); //要转换的类型取决于什么类型的泛型集合
//获得在下拉框中选中的IP地址
string ip = cboUsers.SelectedItem.ToString();
//把信息发送给客户端
dicSocket[ip].Send(newBuffer);
}
/// <summary>
/// 服务端选择文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSelect_Click(object sender, EventArgs e)
{
//创建打开对话框
OpenFileDialog ofd = new OpenFileDialog();
//设置菜单条
ofd.Title = "请选择要发送的文件";
//设置初始目录
ofd.InitialDirectory = @"C:\Users\Administrator\Desktop";
//设置文件类型
ofd.Filter = "文本文件|*.txt|音乐文件|*.wav|图片文件|*.jpg|所有文件|*.*";
//运行对话框
ofd.ShowDialog(this);
//获得用户选择的文件路径
string path = ofd.FileName;
//把用户选中的文件路径显示到textbox中
txtPath.Text = path;
}
/// <summary>
/// 向客户端发送文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSendFile_Click(object sender, EventArgs e)
{
using (FileStream fsRead = new FileStream(txtPath.Text, FileMode.OpenOrCreate, FileAccess.Read))
{
//声明一个字节数组,拿到文件的长度就是文件的大小
byte[] buffer = new byte[fsRead.Length];
//实际读取到的有效字节数
int r = fsRead.Read(buffer, 0, buffer.Length);
//声明byte类型的泛型集合
List<byte> list = new List<byte>();
//在集合里存储1-文件
list.Add(1);
list.AddRange(buffer);
byte[] newBuffer = list.ToArray();
//先获得用户选择的IP地址
string ip = cboUsers.SelectedItem.ToString();
//因为发送文件拿不到实际读取的有效字节数,所以要拿到文件的长度
dicSocket[ip].Send(newBuffer);
}
}
/// <summary>
/// 服务端给客户端发送震动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnZD_Click(object sender, EventArgs e)
{
//这个字节数组里只有一个字节
byte[] buffer = new byte[1];
//索引第一个字节赋值为2-震动
buffer[0] = 2;
//拿到选择的客户端
string ip = cboUsers.SelectedItem.ToString();
//拿到客户端发送字节数组
dicSocket[ip].Send(buffer);
}
}
}
客户端:
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 Client客户练习
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//设置全局通信Socket让其他方法可以调用
Socket socketSend;
/// <summary>
/// 客户端连接服务端
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, EventArgs e)
{
try
{
//在客户端创建一个负责跟客户端通信的Socket
socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//获得要连接的服务端的IP地址
IPAddress ip = IPAddress.Parse(txtSever.Text);
//获得要连接的服务端端口号
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//客户端负责通信的Socket去连接服务端的ip地址和端口号
socketSend.Connect(point);
ShowMsg("连接成功");
//创建新线程执行Rec方法
Thread th1 = new Thread(Rec);
//设置后台线程
th1.IsBackground = true;
//标记这个线程可以被cpu执行了
th1.Start();
}
catch
{
}
}
/// <summary>
/// 客户端接收服务端发来的数据
/// </summary>
public void Rec()
{
while (true)
{
try
{
//客户端接收服务端发来的数据
byte[] buffer = new byte[1024 * 1024 * 5];
//实际接收的有效字节数
int r = socketSend.Receive(buffer);
//从字节数组第一位索引开始
byte b = buffer[0];
//接收的是文字
if(b==0)
{
//从字节数组索引第二位开始解码
string str = System.Text.Encoding.UTF8.GetString(buffer, 1, r-1);
ShowMsg(str);
}
//接收的是文件
else if(b==1)
{
//保存对话框
SaveFileDialog sfd = new SaveFileDialog();
//设置菜单条
sfd.Title = "请选择要保存的文件路径";
//设置初始路径
sfd.InitialDirectory = @"C:\Users\Administrator\Desktop";
//设置文件类型
sfd.Filter = "文本文件|*.txt|音乐文件|*.wav|图片文件|*.jpg|所有文件|*.*";
//运行保存对话框
sfd.ShowDialog(this); //win7或win8需要加this是个bug
string path = sfd.FileName;
using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
//从字节数组第二位索引开始,每次实际接收的有效字节数-1
fsWrite.Write(buffer,1, r - 1);
}
MessageBox.Show("保存成功");
}
//接收的是震动
else if(b==2)
{
ZD();
}
}
catch
{
}
}
}
/// <summary>
/// 让客户端震动
/// </summary>
public void ZD()
{
for (int i = 0; i < 200; i++)
{
this.Location = new Point(220, 220);
this.Location = new Point(420, 420);
}
}
/// <summary>
/// 显示服务端的信息
/// </summary>
/// <param name="str"></param>
public void ShowMsg(string str)
{
richLog.AppendText(str + "\r\n");
}
/// <summary>
/// 客户端给服务端发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
//先拿到要发送的消息
string str = richMsg.Text;
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
socketSend.Send(buffer);
}
/// <summary>
/// 取消客户端跨线程的访问
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
}
}