局域网QQ,无客户端和服务端之分,局域网的计算机运行本程序就可以互相看见,可以自由聊天和传文件。
本版较之1.0版的改进之处:
使用数据结构类型传送数据;
增加传文件功能(有进度条);
考虑大家重现本程序方便,本程序一直没有用到任何额外的控件和子窗体
版本依然是在VS2003下编译,只要贴进编译器中就可以重现。
在VS2005下编译只需要在“窗体设计器生成的代码”里面加一句:
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
本版较之1.0版的改进之处:
使用数据结构类型传送数据;
增加传文件功能(有进度条);
考虑大家重现本程序方便,本程序一直没有用到任何额外的控件和子窗体
版本依然是在VS2003下编译,只要贴进编译器中就可以重现。
在VS2005下编译只需要在“窗体设计器生成的代码”里面加一句:
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.IO;
namespace myQQ
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
public bool runing=false; //标志
public UdpClient listen=new UdpClient(2525);
public IPEndPoint End;
public IPAddress groupAddress=IPAddress.Parse("255.255.255.255"); //广播地址
public int groupPort=2525; //广播端口
public IPAddress myIP;
public string myName;
public string romeName;
public IPAddress romeIP;
public string romeCon;
public sendData mySendData = new sendData(); //本地的0号命令发送包
public bool isfile;//传送文件标志
public string savePath;//传文件的保存地址
public string romeFileName;//远程文件名
public string romeFilel;//远程文件用单位表示的长度,格式为 43M或437K
public FileStream sendfilestream;//发送文件流
private System.Windows.Forms.ListBox box;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.TextBox t_rec;
private System.Windows.Forms.TextBox t_send;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button newmsg;
private System.Windows.Forms.Label online;
private System.Windows.Forms.ToolTip toolTip1;
private System.Windows.Forms.ImageList imageList1;
private System.Windows.Forms.LinkLabel linkLabel1;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
private System.Windows.Forms.TextBox t_filep;
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
private System.Windows.Forms.Panel processA;
private System.Windows.Forms.ProgressBar progressBar1;
private System.Windows.Forms.Panel processB;
private System.Windows.Forms.ProgressBar progressBar2;
private System.ComponentModel.IContainer components;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows 窗体设计器生成的代码
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
//数据包格式
public struct sendData
{
public byte commandNo;//命令号 1字节
public IPAddress fromIP;//发送端IP 4字节
public int nameLength; //名字的字节数 4字节
public string computerName;//计算机名 x字节
public IPAddress toIP;//接收端IP; 4字节
public string content;//内容 y字节
}
private void Form1_Load(object sender, System.EventArgs e)
{
End=new IPEndPoint(groupAddress,groupPort);
//初始化计算机名和端口
IPHostEntry myentry=Dns.GetHostByName(Dns.GetHostName());
myIP = new IPAddress(myentry.AddressList[0].Address);
myName = Dns.GetHostName();
box.Items.Add("IP 主机名");
//开启监听线程
runing=true;
Thread myThread=new Thread(new ThreadStart(this.ListenPort));
myThread.IsBackground = false;
myThread.Start();
//发送上线信息
mySendData.commandNo = 0;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = myIP;
mySendData.content = "上线提示";
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
//初始化窗体位置
t_send.Height=120;
t_send.Top=224;
linkLabel1.Text="传文件";
processA.Visible=false;//发送的进度
processB.Visible=false;//接收的进度
}
//侦听指定端口的广播地址UDP包
public void ListenPort()
{
IPEndPoint tempEnd=new IPEndPoint(IPAddress.Any,2525);
while(runing)
{
Application.DoEvents();
try
{
byte[] recb=listen.Receive(ref tempEnd);
// 检查所接收到的信息and处理之
checkMessage(recb);
}
catch(Exception e)
{
MessageBox.Show("出现错误:"+e.Message.ToString());
break;
}
}
listen.Close();
box.Items.Add("线程已经退出!");
runing=false;
}
//循环接收包
public void checkMessage(byte[] recbb)
{
sendData recData=BytesToStruct(recbb);
romeName=recData.computerName;
romeIP=recData.fromIP;
romeCon=recData.content;
switch(recData.commandNo)
{
case 0x00: //刷新
if (recData.toIP.Equals(myIP))
{
if(box.FindString(recData.fromIP.ToString()+" "+recData.computerName)<=0)
box.Items.Add(recData.fromIP.ToString() + " " + recData.computerName);
online.Text="在线用户:"+(box.Items.Count-1)+"人";
}
else if(recData.fromIP.Equals(recData.toIP))
{
//从其他机器发送过来的刷新请求
//返回自己的信息
mySendData.commandNo = 0x00;
mySendData.toIP = recData.toIP;
mySendData.content = "上线提示";
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
//如果不存在则添加该用户
if (box.FindString(recData.fromIP.ToString() + " " + recData.computerName) <= 0)
box.Items.Add(recData.fromIP.ToString() + " " + recData.computerName);
}
break;
case 0x01: //发言
if (recData.toIP.Equals(myIP)&&!isfile)
{//当传送的不包含文件时才显示“有新消息了”
showNe();
}
break;
case 0x02: //请求传文件
if(recData.toIP.Equals(myIP))
{//准备接收文件
romeFileName=romeCon.Split('+')[0];
romeFilel=romeCon.Split('+')[1];
readyRecFile();
}
break;
case 0x03://传文件
if(recData.toIP.Equals(myIP))
{//传送文件
Thread mysend=new Thread(new ThreadStart(sendFile));
mysend.Start();
}
break;
case 0x09: //确认包
if (recData.toIP.Equals(myIP))
MessageBox.Show("信息来自:"+recData.computerName+"("+recData.fromIP.ToString()+")\r\n"+recData.content,"消息");
break;
}
}
//发送数据包到广播地址
public void SendPack(byte[] sendbs)
{
try
{
listen.Send(sendbs, sendbs.Length, End);
}
catch(Exception e)
{
MessageBox.Show(e.Message.ToString());
}
}
//struct转换成byte[]
public static byte[] StructToBytes(sendData structObj)
{
byte[] commandb=new byte[1];
commandb[0]=structObj.commandNo;
byte[] fromipb=structObj.fromIP.GetAddressBytes();
byte[] nameb=Encoding.Default.GetBytes(structObj.computerName);
byte[] lengthb=BitConverter.GetBytes(nameb.Length);
byte[] toipb=structObj.toIP.GetAddressBytes();
byte[] contentb=Encoding.Default.GetBytes(structObj.content);
byte[] buffer=new byte[13+nameb.Length+contentb.Length];
int index=0;
commandb.CopyTo(buffer,index);
index+=commandb.Length;
fromipb.CopyTo(buffer,index);
index+=fromipb.Length;
lengthb.CopyTo(buffer,index);
index+=lengthb.Length;
nameb.CopyTo(buffer,index);
index+=nameb.Length;
toipb.CopyTo(buffer,index);
index+=toipb.Length;
contentb.CopyTo(buffer,index);
return buffer;
}
//byte转换成struct
public static sendData BytesToStruct(byte[] bytes)
{
sendData myre=new sendData();
myre.commandNo=bytes[0];
byte[] ipb=new byte[4];
Array.Copy(bytes,1,ipb,0,4);
myre.fromIP=IPAddress.Parse(ipByteToString(ipb));
myre.nameLength=BitConverter.ToInt32(bytes,5);
myre.computerName=Encoding.Default.GetString(bytes,9,myre.nameLength);
Array.Copy(bytes,9+myre.nameLength,ipb,0,4);
myre.toIP=IPAddress.Parse(ipByteToString(ipb));
myre.content=Encoding.Default.GetString(bytes,13+myre.nameLength,bytes.Length-13-myre.nameLength);
return myre;
}
//将byte[]表示的IP地址转换成IPAddress类型
public static string ipByteToString(byte[] ipbt)
{
string temp="";
temp=(int)ipbt[0]+"."+(int)ipbt[1]+"."+(int)ipbt[2]+"."+(int)ipbt[3];
return temp;
}
//刷新
private void button3_Click(object sender, System.EventArgs e)
{
box.Items.Clear();
box.Items.Add("IP 主机名");
mySendData.commandNo = 0;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = myIP;
mySendData.content = "上线提示";
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
}
//关闭循环
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
runing=false;
UdpClient mm=new UdpClient();
IPEndPoint tempIPEnd=new IPEndPoint(IPAddress.Parse("127.0.0.1"),2525);
mySendData.commandNo = 0;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = myIP;
mySendData.content = "上线提示";
byte[] sendb = StructToBytes(mySendData);
mm.Send(sendb,sendb.Length,tempIPEnd);
}
//发送
private void button1_Click(object sender, System.EventArgs e)
{
if(box.SelectedItem==null||box.SelectedIndex==0)
{
MessageBox.Show("请先选择一个用户!");
return;
}
if(linkLabel1.Text=="不传文件"&&t_filep.Text!="")
{//需要传文件
//首先发送2号命令 要求对方准备接收
sendfilestream=new FileStream(t_filep.Text,FileMode.Open,FileAccess.Read);
long filelength=sendfilestream.Length;
string totalsteps;
int temp;
if(filelength/(1024*1024)>10)
{//文件>10M时用M做为进度最小单位
temp=(int)(filelength/(1024*1024));
totalsteps=temp+"M";
}
else
{//小于10M的文件用k做为最小单位
temp=(int)(filelength/1024);
totalsteps=temp+"K";
}
//用做接收端时的公共变量保存发送的临时值
romeFilel=totalsteps;
string filename=Path.GetFileName(t_filep.Text);
mySendData.commandNo = 0x02;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = IPAddress.Parse(box.SelectedItem.ToString().Split(' ')[0]);
mySendData.content = filename+"+"+totalsteps;//格式:yy.txt+62K+64990
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
//界面上的处理
t_send.Height=120;
t_send.Top=224;
linkLabel1.Text="传文件";
}
//发言
if(t_send.Text=="")
{
return;
}
mySendData.commandNo = 0x01;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = IPAddress.Parse(box.SelectedItem.ToString().Split(' ')[0]);
mySendData.content = t_send.Text;
byte[] sendb2 = StructToBytes(mySendData);
SendPack(sendb2);
}
//清空
private void button2_Click(object sender, System.EventArgs e)
{
t_send.Text=string.Empty;
t_rec.Text=string.Empty;
}
//单击显示接收的信息并隐藏自身
private void newmsg_Click(object sender, System.EventArgs e)
{
if(isfile)
{//当传送的含有文件时
saveFileDialog1.Filter="所有格式|*.*";
saveFileDialog1.FileName=romeFileName;
if(saveFileDialog1.ShowDialog()==DialogResult.OK)
savePath=saveFileDialog1.FileName;
else
return;
t_rec.Text="消息来自"+romeName+"("+romeIP.ToString()+")"+DateTime.Now.ToShortDateString();
t_rec.Text+="\r\n> "+romeCon;
//界面的处理
newmsg.SendToBack();
t_send.Height=120;
t_send.Top=224;
linkLabel1.Text="传文件";
//返回一个确认接收包
mySendData.commandNo = 0x03;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = romeIP;
mySendData.content = "ready!";
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
//复位文件标志
isfile=false;
//同时开启线程开始监听
Thread myrecv=new Thread(new ThreadStart(listenPort));
myrecv.Start();
return;
}
t_rec.Text="消息来自"+romeName+"("+romeIP.ToString()+")"+DateTime.Now.ToShortDateString();
t_rec.Text+="\r\n> "+romeCon;
mySendData.commandNo = 0x09;
mySendData.toIP = romeIP;
mySendData.content = "信息被打开!";
byte[] sendb2 = StructToBytes(mySendData);
SendPack(sendb2);
newmsg.SendToBack();
}
//当有信息时显示提示按钮
public void showNe()
{
//窗体显示
if(this.WindowState!=FormWindowState.Normal)
{
this.Visible=true;
this.WindowState=FormWindowState.Normal;
}
newmsg.Text="有新消息了";
newmsg.BringToFront();
}
//准备接收文件
public void readyRecFile()
{
//窗体显示
if(this.WindowState!=FormWindowState.Normal)
{
this.Visible=true;
this.WindowState=FormWindowState.Normal;
}
isfile=true;
newmsg.Text=romeFileName+"("+romeFilel+")";
newmsg.BringToFront();
}
//传文件
private void linkLabel1_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
{
if(linkLabel1.Text=="传文件")
{
t_send.Height=80;
t_send.Top=264;
linkLabel1.Text="不传文件";
}
else
{
t_send.Height=120;
t_send.Top=224;
linkLabel1.Text="传文件";
}
}
//打开文件
private void button4_Click(object sender, System.EventArgs e)
{
openFileDialog1.Filter="所有文件|*.*|压缩文件|*.rar";
if(openFileDialog1.ShowDialog()==DialogResult.OK)
{
t_filep.Text=openFileDialog1.FileName;
}
}
//监听文件传送socket的线程——————功能:接收文件
public void listenPort()
{
TcpListener listener=new TcpListener(2626);
listener.Start();
Socket s=listener.AcceptSocket();
FileStream filestream=new FileStream(savePath,FileMode.OpenOrCreate,FileAccess.Write);
NetworkStream stream=new NetworkStream(s);
//定义缓冲区
byte[] bb=new byte[1024];
//循环读socket流
int tt=0;
//进度条
processB.Visible=true;
processB.BackColor=System.Drawing.SystemColors.Control;
int stepoff;
if(romeFilel[romeFilel.Length-1]=='K')
stepoff=1024;
else
stepoff=1024*1024;
int totalste=int.Parse(romeFilel.Substring(0,romeFilel.Length-1));
progressBar2.Maximum=totalste;
progressBar2.Step=totalste/20;
float recbytes=0;
while((tt=stream.Read(bb,0,1024))!=0)
{//接收数据
filestream.Write(bb,0,tt);
filestream.Flush();
//更新进度条
recbytes+=(float)tt/stepoff;
progressBar2.Value=(int)recbytes;
}
filestream.Close();
processB.Visible=false;
MessageBox.Show("文件接收完毕!");
}
//传送文件的线程————————功能:发送文件服务端
public void sendFile()
{
TcpClient serverClient=new TcpClient();
serverClient.Connect(romeIP,2626);
NetworkStream stream=serverClient.GetStream();
//定义缓冲区
byte[] bb=new byte[1024];
//循环读文件
int number;
//进度条
processA.Visible=true;
processA.BackColor=System.Drawing.SystemColors.Window;
int stepoff;
if(romeFilel[romeFilel.Length-1]=='K')
stepoff=1024;
else
stepoff=1024*1024;
int totalste=int.Parse(romeFilel.Substring(0,romeFilel.Length-1));
progressBar1.Maximum=totalste;
progressBar1.Step=totalste/20;
float sendedbytes=0;
while((number=sendfilestream.Read(bb,0,1024))!=0)
{//向客户端发送流
stream.Write(bb,0,number);
//刷新流
stream.Flush();
//进度条
sendedbytes+=(float)number/stepoff;
progressBar1.Value=(int)sendedbytes;
}
sendfilestream.Close();
stream.Close();
processA.Visible=false;
MessageBox.Show("文件传送完毕!");
}
}
}
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.IO;
namespace myQQ
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
public bool runing=false; //标志
public UdpClient listen=new UdpClient(2525);
public IPEndPoint End;
public IPAddress groupAddress=IPAddress.Parse("255.255.255.255"); //广播地址
public int groupPort=2525; //广播端口
public IPAddress myIP;
public string myName;
public string romeName;
public IPAddress romeIP;
public string romeCon;
public sendData mySendData = new sendData(); //本地的0号命令发送包
public bool isfile;//传送文件标志
public string savePath;//传文件的保存地址
public string romeFileName;//远程文件名
public string romeFilel;//远程文件用单位表示的长度,格式为 43M或437K
public FileStream sendfilestream;//发送文件流
private System.Windows.Forms.ListBox box;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.TextBox t_rec;
private System.Windows.Forms.TextBox t_send;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button newmsg;
private System.Windows.Forms.Label online;
private System.Windows.Forms.ToolTip toolTip1;
private System.Windows.Forms.ImageList imageList1;
private System.Windows.Forms.LinkLabel linkLabel1;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
private System.Windows.Forms.TextBox t_filep;
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
private System.Windows.Forms.Panel processA;
private System.Windows.Forms.ProgressBar progressBar1;
private System.Windows.Forms.Panel processB;
private System.Windows.Forms.ProgressBar progressBar2;
private System.ComponentModel.IContainer components;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows 窗体设计器生成的代码
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
//数据包格式
public struct sendData
{
public byte commandNo;//命令号 1字节
public IPAddress fromIP;//发送端IP 4字节
public int nameLength; //名字的字节数 4字节
public string computerName;//计算机名 x字节
public IPAddress toIP;//接收端IP; 4字节
public string content;//内容 y字节
}
private void Form1_Load(object sender, System.EventArgs e)
{
End=new IPEndPoint(groupAddress,groupPort);
//初始化计算机名和端口
IPHostEntry myentry=Dns.GetHostByName(Dns.GetHostName());
myIP = new IPAddress(myentry.AddressList[0].Address);
myName = Dns.GetHostName();
box.Items.Add("IP 主机名");
//开启监听线程
runing=true;
Thread myThread=new Thread(new ThreadStart(this.ListenPort));
myThread.IsBackground = false;
myThread.Start();
//发送上线信息
mySendData.commandNo = 0;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = myIP;
mySendData.content = "上线提示";
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
//初始化窗体位置
t_send.Height=120;
t_send.Top=224;
linkLabel1.Text="传文件";
processA.Visible=false;//发送的进度
processB.Visible=false;//接收的进度
}
//侦听指定端口的广播地址UDP包
public void ListenPort()
{
IPEndPoint tempEnd=new IPEndPoint(IPAddress.Any,2525);
while(runing)
{
Application.DoEvents();
try
{
byte[] recb=listen.Receive(ref tempEnd);
// 检查所接收到的信息and处理之
checkMessage(recb);
}
catch(Exception e)
{
MessageBox.Show("出现错误:"+e.Message.ToString());
break;
}
}
listen.Close();
box.Items.Add("线程已经退出!");
runing=false;
}
//循环接收包
public void checkMessage(byte[] recbb)
{
sendData recData=BytesToStruct(recbb);
romeName=recData.computerName;
romeIP=recData.fromIP;
romeCon=recData.content;
switch(recData.commandNo)
{
case 0x00: //刷新
if (recData.toIP.Equals(myIP))
{
if(box.FindString(recData.fromIP.ToString()+" "+recData.computerName)<=0)
box.Items.Add(recData.fromIP.ToString() + " " + recData.computerName);
online.Text="在线用户:"+(box.Items.Count-1)+"人";
}
else if(recData.fromIP.Equals(recData.toIP))
{
//从其他机器发送过来的刷新请求
//返回自己的信息
mySendData.commandNo = 0x00;
mySendData.toIP = recData.toIP;
mySendData.content = "上线提示";
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
//如果不存在则添加该用户
if (box.FindString(recData.fromIP.ToString() + " " + recData.computerName) <= 0)
box.Items.Add(recData.fromIP.ToString() + " " + recData.computerName);
}
break;
case 0x01: //发言
if (recData.toIP.Equals(myIP)&&!isfile)
{//当传送的不包含文件时才显示“有新消息了”
showNe();
}
break;
case 0x02: //请求传文件
if(recData.toIP.Equals(myIP))
{//准备接收文件
romeFileName=romeCon.Split('+')[0];
romeFilel=romeCon.Split('+')[1];
readyRecFile();
}
break;
case 0x03://传文件
if(recData.toIP.Equals(myIP))
{//传送文件
Thread mysend=new Thread(new ThreadStart(sendFile));
mysend.Start();
}
break;
case 0x09: //确认包
if (recData.toIP.Equals(myIP))
MessageBox.Show("信息来自:"+recData.computerName+"("+recData.fromIP.ToString()+")\r\n"+recData.content,"消息");
break;
}
}
//发送数据包到广播地址
public void SendPack(byte[] sendbs)
{
try
{
listen.Send(sendbs, sendbs.Length, End);
}
catch(Exception e)
{
MessageBox.Show(e.Message.ToString());
}
}
//struct转换成byte[]
public static byte[] StructToBytes(sendData structObj)
{
byte[] commandb=new byte[1];
commandb[0]=structObj.commandNo;
byte[] fromipb=structObj.fromIP.GetAddressBytes();
byte[] nameb=Encoding.Default.GetBytes(structObj.computerName);
byte[] lengthb=BitConverter.GetBytes(nameb.Length);
byte[] toipb=structObj.toIP.GetAddressBytes();
byte[] contentb=Encoding.Default.GetBytes(structObj.content);
byte[] buffer=new byte[13+nameb.Length+contentb.Length];
int index=0;
commandb.CopyTo(buffer,index);
index+=commandb.Length;
fromipb.CopyTo(buffer,index);
index+=fromipb.Length;
lengthb.CopyTo(buffer,index);
index+=lengthb.Length;
nameb.CopyTo(buffer,index);
index+=nameb.Length;
toipb.CopyTo(buffer,index);
index+=toipb.Length;
contentb.CopyTo(buffer,index);
return buffer;
}
//byte转换成struct
public static sendData BytesToStruct(byte[] bytes)
{
sendData myre=new sendData();
myre.commandNo=bytes[0];
byte[] ipb=new byte[4];
Array.Copy(bytes,1,ipb,0,4);
myre.fromIP=IPAddress.Parse(ipByteToString(ipb));
myre.nameLength=BitConverter.ToInt32(bytes,5);
myre.computerName=Encoding.Default.GetString(bytes,9,myre.nameLength);
Array.Copy(bytes,9+myre.nameLength,ipb,0,4);
myre.toIP=IPAddress.Parse(ipByteToString(ipb));
myre.content=Encoding.Default.GetString(bytes,13+myre.nameLength,bytes.Length-13-myre.nameLength);
return myre;
}
//将byte[]表示的IP地址转换成IPAddress类型
public static string ipByteToString(byte[] ipbt)
{
string temp="";
temp=(int)ipbt[0]+"."+(int)ipbt[1]+"."+(int)ipbt[2]+"."+(int)ipbt[3];
return temp;
}
//刷新
private void button3_Click(object sender, System.EventArgs e)
{
box.Items.Clear();
box.Items.Add("IP 主机名");
mySendData.commandNo = 0;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = myIP;
mySendData.content = "上线提示";
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
}
//关闭循环
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
runing=false;
UdpClient mm=new UdpClient();
IPEndPoint tempIPEnd=new IPEndPoint(IPAddress.Parse("127.0.0.1"),2525);
mySendData.commandNo = 0;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = myIP;
mySendData.content = "上线提示";
byte[] sendb = StructToBytes(mySendData);
mm.Send(sendb,sendb.Length,tempIPEnd);
}
//发送
private void button1_Click(object sender, System.EventArgs e)
{
if(box.SelectedItem==null||box.SelectedIndex==0)
{
MessageBox.Show("请先选择一个用户!");
return;
}
if(linkLabel1.Text=="不传文件"&&t_filep.Text!="")
{//需要传文件
//首先发送2号命令 要求对方准备接收
sendfilestream=new FileStream(t_filep.Text,FileMode.Open,FileAccess.Read);
long filelength=sendfilestream.Length;
string totalsteps;
int temp;
if(filelength/(1024*1024)>10)
{//文件>10M时用M做为进度最小单位
temp=(int)(filelength/(1024*1024));
totalsteps=temp+"M";
}
else
{//小于10M的文件用k做为最小单位
temp=(int)(filelength/1024);
totalsteps=temp+"K";
}
//用做接收端时的公共变量保存发送的临时值
romeFilel=totalsteps;
string filename=Path.GetFileName(t_filep.Text);
mySendData.commandNo = 0x02;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = IPAddress.Parse(box.SelectedItem.ToString().Split(' ')[0]);
mySendData.content = filename+"+"+totalsteps;//格式:yy.txt+62K+64990
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
//界面上的处理
t_send.Height=120;
t_send.Top=224;
linkLabel1.Text="传文件";
}
//发言
if(t_send.Text=="")
{
return;
}
mySendData.commandNo = 0x01;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = IPAddress.Parse(box.SelectedItem.ToString().Split(' ')[0]);
mySendData.content = t_send.Text;
byte[] sendb2 = StructToBytes(mySendData);
SendPack(sendb2);
}
//清空
private void button2_Click(object sender, System.EventArgs e)
{
t_send.Text=string.Empty;
t_rec.Text=string.Empty;
}
//单击显示接收的信息并隐藏自身
private void newmsg_Click(object sender, System.EventArgs e)
{
if(isfile)
{//当传送的含有文件时
saveFileDialog1.Filter="所有格式|*.*";
saveFileDialog1.FileName=romeFileName;
if(saveFileDialog1.ShowDialog()==DialogResult.OK)
savePath=saveFileDialog1.FileName;
else
return;
t_rec.Text="消息来自"+romeName+"("+romeIP.ToString()+")"+DateTime.Now.ToShortDateString();
t_rec.Text+="\r\n> "+romeCon;
//界面的处理
newmsg.SendToBack();
t_send.Height=120;
t_send.Top=224;
linkLabel1.Text="传文件";
//返回一个确认接收包
mySendData.commandNo = 0x03;
mySendData.fromIP = myIP;
mySendData.computerName = myName;
mySendData.toIP = romeIP;
mySendData.content = "ready!";
byte[] sendb = StructToBytes(mySendData);
SendPack(sendb);
//复位文件标志
isfile=false;
//同时开启线程开始监听
Thread myrecv=new Thread(new ThreadStart(listenPort));
myrecv.Start();
return;
}
t_rec.Text="消息来自"+romeName+"("+romeIP.ToString()+")"+DateTime.Now.ToShortDateString();
t_rec.Text+="\r\n> "+romeCon;
mySendData.commandNo = 0x09;
mySendData.toIP = romeIP;
mySendData.content = "信息被打开!";
byte[] sendb2 = StructToBytes(mySendData);
SendPack(sendb2);
newmsg.SendToBack();
}
//当有信息时显示提示按钮
public void showNe()
{
//窗体显示
if(this.WindowState!=FormWindowState.Normal)
{
this.Visible=true;
this.WindowState=FormWindowState.Normal;
}
newmsg.Text="有新消息了";
newmsg.BringToFront();
}
//准备接收文件
public void readyRecFile()
{
//窗体显示
if(this.WindowState!=FormWindowState.Normal)
{
this.Visible=true;
this.WindowState=FormWindowState.Normal;
}
isfile=true;
newmsg.Text=romeFileName+"("+romeFilel+")";
newmsg.BringToFront();
}
//传文件
private void linkLabel1_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
{
if(linkLabel1.Text=="传文件")
{
t_send.Height=80;
t_send.Top=264;
linkLabel1.Text="不传文件";
}
else
{
t_send.Height=120;
t_send.Top=224;
linkLabel1.Text="传文件";
}
}
//打开文件
private void button4_Click(object sender, System.EventArgs e)
{
openFileDialog1.Filter="所有文件|*.*|压缩文件|*.rar";
if(openFileDialog1.ShowDialog()==DialogResult.OK)
{
t_filep.Text=openFileDialog1.FileName;
}
}
//监听文件传送socket的线程——————功能:接收文件
public void listenPort()
{
TcpListener listener=new TcpListener(2626);
listener.Start();
Socket s=listener.AcceptSocket();
FileStream filestream=new FileStream(savePath,FileMode.OpenOrCreate,FileAccess.Write);
NetworkStream stream=new NetworkStream(s);
//定义缓冲区
byte[] bb=new byte[1024];
//循环读socket流
int tt=0;
//进度条
processB.Visible=true;
processB.BackColor=System.Drawing.SystemColors.Control;
int stepoff;
if(romeFilel[romeFilel.Length-1]=='K')
stepoff=1024;
else
stepoff=1024*1024;
int totalste=int.Parse(romeFilel.Substring(0,romeFilel.Length-1));
progressBar2.Maximum=totalste;
progressBar2.Step=totalste/20;
float recbytes=0;
while((tt=stream.Read(bb,0,1024))!=0)
{//接收数据
filestream.Write(bb,0,tt);
filestream.Flush();
//更新进度条
recbytes+=(float)tt/stepoff;
progressBar2.Value=(int)recbytes;
}
filestream.Close();
processB.Visible=false;
MessageBox.Show("文件接收完毕!");
}
//传送文件的线程————————功能:发送文件服务端
public void sendFile()
{
TcpClient serverClient=new TcpClient();
serverClient.Connect(romeIP,2626);
NetworkStream stream=serverClient.GetStream();
//定义缓冲区
byte[] bb=new byte[1024];
//循环读文件
int number;
//进度条
processA.Visible=true;
processA.BackColor=System.Drawing.SystemColors.Window;
int stepoff;
if(romeFilel[romeFilel.Length-1]=='K')
stepoff=1024;
else
stepoff=1024*1024;
int totalste=int.Parse(romeFilel.Substring(0,romeFilel.Length-1));
progressBar1.Maximum=totalste;
progressBar1.Step=totalste/20;
float sendedbytes=0;
while((number=sendfilestream.Read(bb,0,1024))!=0)
{//向客户端发送流
stream.Write(bb,0,number);
//刷新流
stream.Flush();
//进度条
sendedbytes+=(float)number/stepoff;
progressBar1.Value=(int)sendedbytes;
}
sendfilestream.Close();
stream.Close();
processA.Visible=false;
MessageBox.Show("文件传送完毕!");
}
}
}