C#winform客户端Socket文件传输(多对1)
服务端在上一篇文章
客户端
代码
Thread threadClient = null; // 创建用于接收服务端消息的 线程;
Client client = new Client();
public static TextBox textBox;
public Form1()
{
InitializeComponent();
textBox = txtSelectFile;
TextBox.CheckForIllegalCrossThreadCalls = false;
}
private void btnSelectFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.InitialDirectory = "D:\\";
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtSelectFile.Text = ofd.FileName;
}
}
private void btnSendFile_Click(object sender, EventArgs e)
{
client.FS();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult result = MessageBox.Show("是否退出?选否,最小化到托盘", "操作提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
this.Dispose();
}
else if (result == DialogResult.Cancel)
{
e.Cancel = true;
}
else
{
e.Cancel = true;
this.WindowState = FormWindowState.Minimized;
this.Visible = false;
//this.ShowInTaskbar = false;
}
}
private void txtSelectFile_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == Keys.Q) && e.Control)
{
if (this.Visible == true)
this.Visible = false;
else
this.Visible = true;
}
}
private void Form1_Load(object sender, EventArgs e)
{
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 3000;//设置执行间隔单位ms毫秒
t.Tick += new EventHandler(client.Lock);//Lock是要执行的函数
t.Start();//开始计时,开始循环
threadClient = new Thread(client.link); //自动重连线程
threadClient.IsBackground = true;
threadClient.Start();
}
/// <summary>
/// 开机自启
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (cb_zddl.Checked) //设置开机自启动
{
MessageBox.Show("设置开机自启动,需要修改注册表", "提示");
string path = Application.ExecutablePath;
RegistryKey rk = Registry.LocalMachine;
RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
rk2.SetValue("frmClient", path);
rk2.Close();
rk.Close();
}
else //取消开机自启动
{
MessageBox.Show("取消开机自启动,需要修改注册表", "提示");
string path = Application.ExecutablePath;
RegistryKey rk = Registry.LocalMachine;
RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
rk2.DeleteValue("frmClient", false);
rk2.Close();
rk.Close();
}
}
Client类
class Class1
{
public static Socket sockClient = null;
bool Reconnect = false;
Thread threadClient = null; // 创建用于接收服务端消息的 线程;
private string GetIpAddress()
{
string hostName = Dns.GetHostName(); //获取本机名
IPHostEntry localhost = Dns.GetHostByName(hostName); //方法已过期,可以获取IPv4的地址
//IPHostEntry localhost = Dns.GetHostEntry(hostName); //获取IPv6地址
IPAddress localaddr = localhost.AddressList[0];
return localaddr.ToString();
}
/// <summary>
/// 连接服务器
/// </summary>
public void link()
{
string hostName = Dns.GetHostName(); //获取本机名
try
{
IPAddress ip = IPAddress.Parse(GetIpAddress());
IPEndPoint endPoint = new IPEndPoint(ip, 9000);
sockClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//ShowMsg("与服务器连接中……");
while (true) //不断尝试连接
{
try
{
sockClient.Connect(endPoint); //尝试连接
string hName = Dns.GetHostName(); //获取本机名
string strMsg = hName;
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
byte[] arrSendMsg = new byte[arrMsg.Length + 1];
if (!Reconnect)
{
arrSendMsg[0] = 2; // 用来表示发送的是消息数据
Buffer.BlockCopy(arrMsg, 0, arrSendMsg, 1, arrMsg.Length);
sockClient.Send(arrSendMsg); // 发送消息;
threadClient = new Thread(RecMsg); //连接成功后开启新的线程开始监听服务端是否发生消息
threadClient.IsBackground = true;
threadClient.Start();
return; //连接成功后跳出死循环
}
else
{
arrSendMsg[0] = 6; // 用来表示发送的是消息数据
Buffer.BlockCopy(arrMsg, 0, arrSendMsg, 1, arrMsg.Length);
sockClient.Send(arrSendMsg); // 发送消息;
threadClient = new Thread(RecMsg); //连接成功后开启新的线程开始监听服务端是否发生消息
threadClient.IsBackground = true;
threadClient.Start();
Reconnect = false;
return; //连接成功后跳出死循环
}
}
catch (SocketException)
{
//MessageBox.Show(se.Message);
//return;
//this.Close();
}
}
}
catch (Exception)
{
//MessageBox.Show("客户端配置文件不存在请联系管理员" + e.Message);
}
}
void RecMsg()
{
string Fn = "";
while (true)
{
// 定义一个2M的缓存区;
byte[] arrMsgRec = new byte[1024 * 1024 * 100];
// 将接受到的数据存入到输入 arrMsgRec中;
int length = -1;
try
{
length = sockClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
}
catch (SocketException)
{
Reconnect = true;
threadClient = new Thread(link); //自动重连线程
threadClient.IsBackground = true;
threadClient.Start();
}
catch (Exception)
{
Reconnect = true;
threadClient = new Thread(link); //自动重连线程
threadClient.IsBackground = true;
threadClient.Start();
}
if (arrMsgRec[0] == 0) // 表示接收到的是消息数据;
{
try
{
string strMsg = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length - 1);// 将接受到的字节数据转化成字符串;
Fn = strMsg;
//ShowMsg(strMsg);
}
catch (Exception e)
{
MessageBox.Show("与服务器断开连接" + e);
}
}
if (arrMsgRec[0] == 1) // 表示接收到的是文件数据;
{
try
{
string path = System.Windows.Forms.Application.StartupPath;
//判断该路径下文件夹是否存在,不存在的情况下新建文件夹
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string fileSavePath = path + Fn;// 获得文件保存的路径;
// 创建文件流,然后根据路径创建文件;
using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
{
fs.Write(arrMsgRec, 1, length - 1);
}
//System.Diagnostics.Process.Start(fileSavePath);
}
catch (Exception aaa)
{
MessageBox.Show(aaa.Message);
}
}
}
}
public void FS()
{
if (string.IsNullOrEmpty(Form1.textBox.Text))
{
MessageBox.Show("请选择要发送的文件!!!");
}
else
{
// 用文件流打开用户要发送的文件;
using (FileStream fs = new FileStream(Form1.textBox.Text, FileMode.Open))
{
if (fs.Length > 1024 * 1024 * 100)
{
MessageBox.Show("文件大于100M,不能上传");
}
else
{
//在发送文件以前先给好友发送这个文件的名字+扩展名,方便后面的保存操作;
string fileName = System.IO.Path.GetFileName(Form1.textBox.Text);
string fileExtension = System.IO.Path.GetExtension(Form1.textBox.Text);
string strMsg = fileName;
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
byte[] arrSendMsg = new byte[arrMsg.Length + 1];
arrSendMsg[0] = 0; // 用来表示发送的是消息数据
Buffer.BlockCopy(arrMsg, 0, arrSendMsg, 1, arrMsg.Length);
sockClient.Send(arrSendMsg); // 发送消息;
byte[] arrFile = new byte[1024 * 1024 * 100];
int length = fs.Read(arrFile, 0, arrFile.Length); // 将文件中的数据读到arrFile数组中;
byte[] arrFileSend = new byte[length + 1];
arrFileSend[0] = 1; // 用来表示发送的是文件数据;
Buffer.BlockCopy(arrFile, 0, arrFileSend, 1, length);
// 还有一个 CopyTo的方法,但是在这里不适合; 当然还可以用for循环自己转化;
sockClient.Send(arrFileSend);// 发送数据到服务端;
Form1.textBox.Clear();
}
}
}
}
}
客户端搭建完成(服务端与客户端必须在同一网段才可通讯,安装服务端的电脑IP为广域网唯一IP也可通讯)