您的位置:首页 > 编程语言 > C#

c# winform 音视频 文件传输

2019-05-22 16:29 2111 查看

此程序分服务端以及客户端,服务端负责信息的中转,最终实现微信的效果,服务器可挂在公务,并做了心跳检测。
客户端只需要能上网既能实现点对点通讯
采用TCP UDP混合异步编程
解决TCP粘包问题 以及UDP分包发送问题
可用于二次开发,值得深入学习

服务端代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using vjsdn.net.library;
using System.Windows.Forms;
using Common;
using Newtonsoft.Json;
using LitJson;
using System.Linq;
using System.IO;
using System.Diagnostics;

namespace vjsdn.net.library
{
///
///
/// 服务器端业务类
///
///
public class Server
{
private UdpClient _server; //服务器端消息监听器
private Socket serverListener; //客户监听器
public UserCollection _userList; //在线用户列表
public TCPUserCollection _TCPuserList; //在线用户列表
private Thread _serverThread;
private IPEndPoint _remotePoint; //远程用户请求的IP地址及端口
private Dictionary<string, string> userCollection;
private WriteLogHandle _WriteLogHandle = null;
private UserChangedHandle _UserChangedHandle = null;
////心跳包发送给客户端后,如果客户端有应答,那么下面这个集合中的value将一直保持为0的状态,否则就累加,一旦累加大于等于3次,则视为掉线。
public Dictionary<string, int> userOnLineCounter;
private AutoResetEvent syncHeartbeatSend;
private AutoResetEvent resetEvent;
private AutoResetEvent resetEventForListener;
[System.Runtime.InteropServices.DllImport(“psapi.dll”)]
private static extern int EmptyWorkingSet(int hProcess);
///
/// 显示跟踪消息
///
public WriteLogHandle OnWriteLog
{
get { return _WriteLogHandle; }
set { _WriteLogHandle = value; }
}

/// <summary>
/// 当用户登入/登出时触发此事件
/// </summary>
public UserChangedHandle OnUserChanged
{
get { return _UserChangedHandle; }
set { _UserChangedHandle = value; }
}

/// <summary>
/// 构造器
/// </summary>
public Server()
{

_userList = new UserCollection();
_TCPuserList = new TCPUserCollection();
_remotePoint = new IPEndPoint(IPAddress.Any, 0);
_serverThread = new Thread(new ThreadStart(Run));
resetEvent = new AutoResetEvent(false);
resetEventForListener = new AutoResetEvent(false);
serverListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}

/// <summary>
///显示跟踪记录
/// </summary>
/// <param name="log"></param>
private void DoWriteLog(string log)
{
if (_WriteLogHandle != null)
(_WriteLogHandle.Target as System.Windows.Forms.Control).Invoke(_WriteLogHandle, log);
}

/// <summary>
/// 刷新用户列表
/// </summary>
/// <param name="list">用户列表</param>
private void DoUserChanged(UserCollection list)
{
if (_UserChangedHandle != null)
(_UserChangedHandle.Target as Control).Invoke(_UserChangedHandle, list);
}

#region --开启服务--
public void Start()
{
try
{

userCollection = new Dictionary<string, string>();
userOnLineCounter = new Dictionary<string, int>(); //心跳
syncHeartbeatSend = new AutoResetEvent(false);//心跳
_server = new UdpClient(5000);
_serverThread.Start();

//serverListener = new TcpListener(5001);

IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 5001);
serverListener.Bind(ipEnd);
serverListener.Listen(100);
serverListener.NoDelay = false;
serverListener.ReceiveTimeout = 1000000;
serverListener.BeginAccept(new AsyncCallback(ClientConnectComplete), null);
//serverListener.Start();
//AcceptClientsThread();

DoWriteLog("服务器已经启动,监听端口:" + Globals.SERVER_PORT.ToString() + ",等待客户连接...");
}
catch (Exception ex)
{
DoWriteLog("启动服务器发生错误: " + ex.Message);
throw ex;
}
}
#endregion

#region --新接收--
byte[] receiveByte = new byte[1024];
StringBuilder result=new StringBuilder();
private void ClientConnectComplete(IAsyncResult async)
{
TCPuser client;

// 完成接受客户端传入的连接的这个异步操作,并返回客户端连入的 socket
try
{
Socket sk = serverListener.EndAccept(async);
client = new TCPuser(sk);
}
catch (Exception ex)
{

return;
}

//把连接进来的客户端保存起来
//ReceiveClientsThread((object)client);

try
{
StateObject state = new StateObject();

state.workSocket = client.client;
client.client.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ClientReceiveComplete), state);

// 开始异步接收客户端传入的数据
serverListener.BeginAccept(new AsyncCallback(ClientConnectComplete), null);//继续接受下一个连接
}
catch (SocketException ex)
{
// 处理异常
}

}

private void SendToClientComplete(IAsyncResult async)
{
TCPuser client = async.AsyncState as TCPuser;
try
{
// 完成将信息发送到客户端的这个异步操作
if (client.client.Connected)
{
client.client.EndSend(async);
}
}
catch (SocketException ex)
{
// 处理异常
}

}

string strresult;

//#endregion

#region --tcp 解析包--
private void TCPAnalysisPackage(MessageEntity entity, TCPuser user)
{
switch (entity.MessageType)
{
case MessagePicks.OnLine:
user.name = entity.NickName;

var disconnectedUsers = userOnLineCounter.Where(p => p.Key == entity.NickName).ToList();
if (disconnectedUsers.Count == 0)
{
userOnLineCounter.Add(entity.NickName, 0);
}
#region --udp--
IPEndPoint userEndPoint = new IPEndPoint(_remotePoint.Address, _remotePoint.Port);
User user2 = new User(entity.NickName, userEndPoint);

var udpuser = _userList.Find(entity.NickName);
if (udpuser == null)
{
_userList.Add(user2);
}

#endregion

var tcpuser = _TCPuserList.Find(entity.NickName);
if (tcpuser == null)
{
_TCPuserList.Add(user);
}
else
{
//user.client.Close();

}

this.DoUserChanged(_userList);
BroadTCPCastUsers();
BroadCastUsers();

break;
case MessagePicks.FileOnLine:

byte[] recvBytes = entity.receiveClientVideoBytes;

if (recvBytes[0] == 0x10 && recvBytes[1] == 0x13)
{

byte[] bytes2 = new byte[]
{
recvBytes[2],
recvBytes[3],
recvBytes[4],
recvBytes[5],
recvBytes[6],
recvBytes[7],
recvBytes[8],
recvBytes[9],
recvBytes[10]
};
string username = Encoding.UTF8.GetString(bytes2).TrimEnd('\0');

#region --心跳--

if (userOnLineCounter.ContainsKey(use
3ff7
rname))
{
userOnLineCounter[username] = 0;
}
else
{
userOnLineCounter.Add(username, 0);
}
#endregion

byte[] array2 = new byte[100];
Buffer.BlockCopy(recvBytes, 11, array2, 0, 100);
string text = Encoding.UTF8.GetString(array2).TrimEnd(new char[1]);

string currPath = Application.StartupPath;
//检查是否存在文件夹
string path = currPath + "\\userFiles\\" + username + "\\";
if (false == System.IO.Directory.Exists(path))
{
//创建pic文件夹
System.IO.Directory.CreateDirectory(path);
}
else
{
}
text = path + text;
bool flag2 = File.Exists(text);
if (flag2)
{
FileStream fileStream = File.Open(text, FileMode.Append);
byte[] array3 = new byte[8192];
Buffer.BlockCopy(recvBytes, 111, array3, 0, 8192);
fileStream.Write(array3, 0, 8192);
fileStream.Close();
}
else
{
FileStream fileStream2 = File.Create(text);
byte[] array4 = new byte[8192];
Buffer.BlockCopy(recvBytes, 111, array4, 0, 8192);
fileStream2.Write(array4, 0, 8192);
fileStream2.Close();
}

}

break;
case MessagePicks.OffLine:
user.name = entity.NickName;
_TCPuserList.Remove(user);
BroadTCPCastUsers();

break;

case MessagePicks.CarryMsg:
var a = _TCPuserList.Find(entity.receiveClient);
string audioJson = JsonConvert.SerializeObject(entity, Formatting.None);
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes("$" + audioJson + "*");
a.client.Send(byteArray);
break;
default: break;
}
}
#endregion

#region --UDP监听--
private System.Collections.ArrayList arr = new System.Collections.ArrayList();
private System.Collections.ArrayList arr2 = new System.Collections.ArrayList();
StringBuilder sb2 = new StringBuilder();

private void Run()
{
byte[] msgBuffer = null;

while (true)
{
try
{
msgBuffer = _server.Receive(ref _remotePoint); //接受消息

int des = 0;
if (msgBuffer[0] == 0x10 && msgBuffer[1] == 0x10)
{
des = 1;
byte[] byteName = new byte[9];
byteName[0] = msgBuffer[2];
byteName[1] = msgBuffer[3];
byteName[2] = msgBuffer[4];
byteName[3] = msgBuffer[5];
byteName[4] = msgBuffer[6];
byteName[5] = msgBuffer[7];
byteName[6] = msgBuffer[8];
byteName[7] = msgBuffer[9];
byteName[8] = msgBuffer[10];
string name = System.Text.Encoding.UTF8.GetString(byteName);
User user5 = _userList.Find(name.TrimEnd('\0'));

arr.Capacity = 30;

byte[] bytes1 = msgBuffer;
arr.Add(bytes1);
byte[] newbytes = (byte[])arr[0];
arr.RemoveAt(0);
//messageID = DateTime.Now.ToString();

//int len = SendByte.Length;
int totalSize = newbytes.Length;
//***********小于mtu的数据包做标记直接发送****************
//如果总包超过udp的最大传输自己即MTU,则进行分包
if (totalSize < 1)
{           //数据小于60000字节,进行标记,方便Client接收
byte[] b1 = new byte[totalSize + 1];
b1[0] = 1;
//给小于MTU的数据包做标记
Array.Copy(newbytes, 0, b1, 1, totalSize);
_server.Send(b1, b1.Length, user5.NetPoint);

}
//**************大于mtu的数据包进行分包,然后发送**********
else
{
//分包的大小
int PacketSize = 1000;
//分包的数量
int PacketCount = 0;
//分包个数的控制
//totalSize/PacketSize*PacketSize   只有两中情况,等于totalsize   或者是大于

if (totalSize / PacketSize * PacketSize < totalSize)
{ PacketCount = totalSize / PacketSize + 1; }
else
{ PacketCount = totalSize / PacketSize; }

int start = 0;
//数据包
byte[] data = new byte[PacketSize + 4];
//开始循环发送数据包
for (int i = 0; i < PacketCount - 1; i++)
{

//第一个字节表示包的大小,第二字节表示第几个包,第三、四个字节
data[0] = Convert.ToByte(PacketCount);
data[1] = (byte)i;
data[2] = 0x10;
//表示第几个包
data[3] = 0x10;

//填充数据包;从bytes源数组提取数据。
Array.Copy(newbytes, start, data, 4, data.Length - 4);
start += PacketSize;

_server.Send(data, data.Length, user5.NetPoint);

}

//最后一个包的发送
//if (i == PacketCount - 1)
//{
//最后一个包的大小 ,总长减掉之前拷贝的数据长度
//int LastDataPacket = (int)(totalSize - ((long)(PacketSize * i)));
int LastDataPacket = (int)(totalSize - start);
//最后一个包剩余的大小 ,加上报头长度
//data = new byte[LastDataPacket + 4];
data = new byte[LastDataPacket + 6];
//最后一个数据包的起始位置
//int LastDataPacketBegin = totalSize - LastDataPacket;
//int LastDataPacketBegin = i * PacketSize;
int LastDataPacketBegin = start;
//给最后一个数据包的前两个自己打标
//data[0] = 0;
data[0] = Convert.ToByte(PacketCount);
data[1] = (byte)(PacketCount - 1);
data[2] = 0x10;
data[3] = 0x10;
//将最后一个数据包的大小放入两个byte中
data[4] = (byte)(LastDataPacket / 256);
data[5] = (byte)(LastDataPacket % 256);
//data[4]=(byte) (LastDataPacket>>16);//平移16位
//data[5]=(byte) (LastDataPacket>>24);
Array.Copy(newbytes, LastDataPacketBegin, data, 6, LastDataPacket);

_server.Send(data, data.Length, user5.NetPoint);
//System.Threading.Thread.Sleep(5);
}

}
if (msgBuffer[0] == 0x10 && msgBuffer[1] == 0x11)
{
des = 1;
byte[] byteName = new byte[9];
byteName[0] = msgBuffer[2];
byteName[1] = msgBuffer[3];
byteName[2] = msgBuffer[4];
byteName[3] = msgBuffer[5];
byteName[4] = msgBuffer[6];
byteName[5] = msgBuffer[7];
byteName[6] = msgBuffer[8];
byteName[7] = msgBuffer[9];
byteName[8] = msgBuffer[10];
string name = System.Text.Encoding.UTF8.GetString(byteName);
User user5 = _userList.Find(name.TrimEnd('\0'));

arr2.Capacity = 30;

byte[] bytes1 = msgBuffer;
arr2.Add(bytes1);
byte[] newbytes = (byte[])arr2[0];
arr2.RemoveAt(0);
//messageID = DateTime.Now.ToString();

//int len = SendByte.Length;
int totalSize = newbytes.Length;
//***********小于mtu的数据包做标记直接发送****************
//如果总包超过udp的最大传输自己即MTU,则进行分包
if (totalSize < 1)
{           //数据小于60000字节,进行标记,方便Client接收
byte[] b1 = new byte[totalSize + 1];
b1[0] = 1;
//给小于MTU的数据包做标记
Array.Copy(newbytes, 0, b1, 1, totalSize);
_server.Send(b1, b1.Length, user5.NetPoint);

}
//**************大于mtu的数据包进行分包,然后发送**********
else
{
//分包的大小
int PacketSize = 1000;
//分包的数量
int PacketCount = 0;
//分包个数的控制
//totalSize/PacketSize*PacketSize   只有两中情况,等于totalsize   或者是大于

if (totalSize / PacketSize * PacketSize < totalSize)
{
PacketCount = totalSize / PacketSize + 1;
}
else
{
PacketCount = totalSize / PacketSize;
}

int start = 0;
//数据包
byte[] data = new byte[PacketSize + 4];
//开始循环发送数据包
for (int i = 0; i < PacketCount - 1; i++)
{

//第一个字节表示包的大小,第二字节表示第几个包,第三、四个字节
data[0] = Convert.ToByte(PacketCount);
data[1] = (byte)i;
data[2] = 0x10;
//表示第几个包
data[3] = 0x11;

//填充数据包;从bytes源数组提取数据。
Array.Copy(newbytes, start, data, 4, data.Length - 4);
start += PacketSize;

_server.Send(data, data.Length, user5.NetPoint);
//System.Threading.Thread.Sleep(5);

}

//最后一个包的发送
//if (i == PacketCount - 1)
//{
//最后一个包的大小 ,总长减掉之前拷贝的数据长度
//int LastDataPacket = (int)(totalSize - ((long)(PacketSize * i)));
int LastDataPacket = (int)(totalSize - start);
//最后一个包剩余的大小 ,加上报头长度
//data = new byte[LastDataPacket + 4];
data = new byte[LastDataPacket + 6];
//最后一个数据包的起始位置
//int LastDataPacketBegin = totalSize - LastDataPacket;
//int LastDataPacketBegin = i * PacketSize;
int LastDataPacketBegin = start;
//给最后一个数据包的前两个自己打标
//data[0] = 0;
data[0] = Convert.ToByte(PacketCount);
data[1] = (byte)(PacketCount - 1);
data[2] = 0x10;
data[3] = 0x11;
//将最后一个数据包的大小放入两个byte中
data[4] = (byte)(LastDataPacket / 256);
data[5] = (byte)(LastDataPacket % 256);
//data[4]=(byte) (LastDataPacket>>16);//平移16位
//data[5]=(byte) (LastDataPacket>>24);
Array.Copy(newbytes, LastDataPacketBegin, data, 6, LastDataPacket);

_server.Send(data, data.Length, user5.NetPoint);

}
}
if (des == 0)
{
sb2.Append(MidStrEx(System.Text.Encoding.UTF8.GetString(msgBuffer), "$", "*"));

MessageEntity entity = (MessageEntity)JsonConvert.DeserializeObject<MessageEntity>(sb2.ToString());
sb2.Clear();
AnalysisPackage(entity, null);
}
}
catch (Exception ex)
{
GC.Collect();
GC.WaitForPendingFinalizers();
EmptyWorkingSet(Process.GetCurrentProcess().Handle.ToInt32());
}

}
}

#endregion

#region -udp解析包--
private void AnalysisPackage(MessageEntity entity, User user2)
{

switch (entity.MessageType)
{

case MessagePicks.OffLine:
User userOffLine = _userList.Find(entity.NickName);

userOnLineCounter.Remove(entity.NickName);
_userList.Remove(userOffLine);

for (int i = 0; i < _TCPuserList.Count; i++)
{
if (_TCPuserList[i].name == entity.NickName)
{
_TCPuserList[i].client.Close();
_TCPuserList.RemoveAt(i);
}
}
this.DoUserChanged(_userList);

BroadCastUsers();
BroadTCPCastUsers();

break;
case MessagePicks.RequestVedio:
User user5 = _userList.Find(entity.receiveClient);
MessageEntity entity5 = new MessageEntity();
entity5.MessageType = MessagePicks.RequestVedio;
entity5.NickName = entity.NickName;
entity5.MessageContent = entity.MessageContent;

this.SendMessage(entity5, user5.NetPoint);

break;
case MessagePicks.AcceptVedio:
User user6 = _userList.Find(entity.receiveClient);
MessageEntity entity6 = new MessageEntity();
entity6.MessageType = MessagePicks.AcceptVedio;
entity6.NickName = entity.NickName;
entity6.MessageContent = entity.MessageContent;
this.SendMessage(entity6, user6.NetPoint);
break;

case MessagePicks.Draw:
User user7 = _userList.Find(entity.receiveClient);
MessageEntity entity7 = new MessageEntity();
entity7.MessageType = MessagePicks.Draw;
entity7.NickName = entity.NickName;

4000
entity7.receiveClientVideoBytes = entity.receiveClientVideoBytes;
entity7.drawPoints = entity.drawPoints;
entity7.MRordinates_upLeft = entity.MRordinates_upLeft;
entity7.MRordinates_upRight = entity.MRordinates_upRight;
entity7.MRordinates_downLeft = entity.MRordinates_downLeft;
entity7.MRordinates_downRight = entity.MRordinates_downRight;
entity7.VedioHeight = entity.VedioHeight;
entity7.VedioWidth = entity.VedioWidth;
string drawJson = JsonMapper.ToJson(entity7);

//MessageEntity aa = JsonMapper.ToObject<MessageEntity>(drawJson);
byte[] drawByte = System.Text.Encoding.UTF8.GetBytes("$" + drawJson + "*");
_server.Send(drawByte, drawByte.Length, user7.NetPoint);

break;
case MessagePicks.ScreenHeightWidth:
User user9 = _userList.Find(entity.receiveClient);
MessageEntity entity9 = new MessageEntity();
entity9.MessageType = MessagePicks.ScreenHeightWidth;

entity9.NickName = entity.NickName;
entity9.VedioHeight = entity.VedioHeight;
entity9.VedioWidth = entity.VedioWidth;
this.SendMessage(entity9, user9.NetPoint);
break;
case MessagePicks.Heartbeat:
syncHeartbeatSend.Set();

if (userOnLineCounter.ContainsKey(entity.NickName))
{
userOnLineCounter[entity.NickName] = 0;
}
else
{
userOnLineCounter.Add(entity.NickName, 0);
}
break;
default: break;
}

}
#endregion

#region --用户登录广播--
public void BroadCastUsers()
{
MessageEntity entity = new MessageEntity();
entity.MessageType = MessagePicks.OnLine;
userCollection.Clear();
for (int i = 0; i < _userList.Count; i++)
{
if (userCollection.ContainsKey(_userList[i].UserName) == false)
{
userCollection.Add(_userList[i].UserName, _userList[i].NetPoint.ToString());
}

}
entity.MessageContentEx = userCollection;

foreach (User u in _userList)
{

SendMessage(entity, u.NetPoint);
}

}

public void BroadTCPCastUsers()
{
MessageEntity entity = new MessageEntity();
entity.MessageType = MessagePicks.OnLine;
Dictionary<string, string> MessageContentEx = new Dictionary<string, string>();
foreach (TCPuser user in _TCPuserList)
{
MessageContentEx.Add(user.name, user.name);
}
entity.MessageContentEx = MessageContentEx;

string msgJson = JsonConvert.SerializeObject(entity, Formatting.None);

byte[] Array = System.Text.Encoding.UTF8.GetBytes("$" + msgJson + "*");

foreach (TCPuser user in _TCPuserList)
{

if (user.client.Connected == true)
{
user.client.Send(Array);

}

}

}
#endregion

#region --发送方法--
/// <summary>
/// 发送消息
/// </summary>
public void SendMessage(MessageEntity msg, IPEndPoint remoteIP)
{
//DoWriteLog("正在发送消息:" + msg.ToString());
if (msg == null) return;
string msgJson = "";

msgJson = JsonConvert.SerializeObject(msg, Formatting.None);
byte[] buffer = System.Text.Encoding.UTF8.GetBytes("$" + msgJson + "*");
_server.Send(buffer, buffer.Length, remoteIP);
//DoWriteLog("消息已发送.");
}

public void Unity_SendMessage(MessageEntity msg, IPEndPoint remoteIP)
{
// DoWriteLog("正在发送消息:" + msg.ToString());
if (msg == null) return;
string msgJson = JsonMapper.ToJson(msg);

byte[] buffer = new byte[msg.receiveClientVideoBytes.Length + 1];
buffer = msg.receiveClientVideoBytes;
buffer[buffer.Length - 1] = 0x11;
_server.Send(buffer, buffer.Length, remoteIP);
// DoWriteLog("消息已发送.");
}

public void TCP_SendMessage(MessageEntity msg)
{

string msgJson = JsonMapper.ToJson(msg);

byte[] Array = System.Text.Encoding.UTF8.GetBytes("$" + msgJson + "*");

foreach (TCPuser user in _TCPuserList)
{

if (user.name == msg.receiveClient)
{
byte[] picslen = new byte[1];
picslen = System.Text.Encoding.UTF8.GetBytes(msg.VedioHeight.ToString());
byte[] filename = new byte[100];
//username = System.Text.Encoding.UTF8.GetBytes(msg.receiveClient);
for (int i = 0; i < System.Text.Encoding.UTF8.GetBytes(msg.NickName).Length; i++)
{
filename[i] = System.Text.Encoding.UTF8.GetBytes(msg.NickName)[i];
}
filename = copybyte(picslen, filename);
byte[] buff = msg.receiveClientVideoBytes;
buff = copybyte(filename, buff);
MemoryStream ms = new MemoryStream(buff);
while (true)
{
byte[] buffer = new byte[1024 * 10];
int len = ms.Read(buffer, 0, buffer.Length);
if (len <= 0) break;
user.client.Send(buffer);
}
user.client.Send(ASCIIEncoding.Default.GetBytes("|E|"));
msg = null;

ms.Close();
ms.Dispose();

//user.writer.Write(Array);
//user.writer.Flush();
}

}
}
#endregion

#region --停止服务--
public void Stop()
{
DoWriteLog("停止服务器...");
try
{
_serverThread.Abort();
_server.Close();
DoWriteLog("服务器已停止.");
}
catch (Exception ex)
{
DoWriteLog("停止服务器发生错误: " + ex.Message);
throw ex;
}
}
#endregion

#region --工具方法--
public byte[] copybyte(byte[] a, byte[] b)
{
byte[] c = new byte[a.Length + b.Length];
a.CopyTo(c, 0);
b.CopyTo(c, a.Length);
return c;
}
public string MidStrEx(string sourse, string startstr, string endstr)
{
string result = string.Empty;
int startindex, endindex;
try
{
startindex = sourse.IndexOf(startstr);
if (startindex == -1)
return result;
string tmpstr = sourse.Substring(startindex + startstr.Length);
endindex = tmpstr.IndexOf(endstr);
if (endindex == -1)
return result;
result = tmpstr.Remove(endindex);
}
catch (Exception ex)
{

}
return result;
}
#endregion

}

}

客户端代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using vjsdn.net.library;
using System.Windows.Forms;
using System.IO;
using Common;
using Newtonsoft.Json;
using System.Linq;

namespace vjsdn.net.library
{
///
/// 客户端业务类
///
public class Client : IDisposable
{
//private const int MAX_RETRY_SEND_MSG = 1; //打洞时连接次数,正常情况下一次就能成功

private UdpClient _client;//客户端监听器
public IPEndPoint _hostPoint; //主机IP
public IPEndPoint _remotePoint; //接收任何远程机器的数据
private UserCollection _userList;//在线用户列表
private Thread _listenThread; //监听线程
private string _LocalUserName; //本地用户名
//private bool _HoleAccepted = false; //A->B,接收到B用户的确认消息

private WriteLogHandle _OnWriteMessage;
public WriteLogHandle OnWriteMessage
{
get { return _OnWriteMessage; }
set { _OnWriteMessage = value; }
}

private UserChangedHandle _UserChangedHandle = null;
public UserChangedHandle OnUserChanged
{
get { return _UserChangedHandle; }
set { _UserChangedHandle = value; }
}
private CallChangedHandle _CallChangedHandle = null;
public CallChangedHandle OnCallChanged
{
get { return _CallChangedHandle; }
set { _CallChangedHandle = value; }
}
private ReceiveCallChangedHandle receiveCallChangedHandle = null;
public ReceiveCallChangedHandle OnReceiveChanged
{
get { return receiveCallChangedHandle; }
set { receiveCallChangedHandle = value; }
}

private ReceivePicChangedHandle _receivePicChangedHandle = null;
public ReceivePicChangedHandle OnReceivePicChanged
{
get { return _receivePicChangedHandle; }
set { _receivePicChangedHandle = value; }
}
private ReceiveAudioChangedHandle _receiveAudioChangedHandle = null;
public ReceiveAudioChangedHandle OnReceiveAudioChanged
{
get { return _receiveAudioChangedHandle; }
set { _receiveAudioChangedHandle = value; }
}
private ReceiveFileChangedHandle _receiveFileChangedHandle = null;
public ReceiveFileChangedHandle OnReceiveFileChanged
{
get { return _receiveFileChangedHandle; }
set { _receiveFileChangedHandle = value; }
}
private ReceiveDrawChangedHandle _receiveDrawChangedHandle = null;
public ReceiveDrawChangedHandle OnReceiveDrawChanged
{
get { return _receiveDrawChangedHandle; }
set { _receiveDrawChangedHandle = value; }
}
private ReceiveScreenSizeChangedHandle _receiveScreenSizeChangedHandle = null;
public ReceiveScreenSizeChangedHandle OnReceiveScreenSizeChanged
{
get { return _receiveScreenSizeChangedHandle; }
set { _receiveScreenSizeChangedHandle = value; }
}
/// <summary>
///显示跟踪记录
/// </summary>
/// <param name="log"></param>
private void DoWriteLog(string log)
{
if (_OnWriteMessage != null)
(_OnWriteMessage.Target as Control).Invoke(_OnWriteMessage, log);
}

/// <summary>
/// 构造器
/// </summary>
/// <param name="serverIP"></param>
public Client()
{
string serverIP = this.GetServerIP();
_remotePoint = new IPEndPoint(IPAddress.Any, 0); //任何与本地连接的用户IP地址。
_hostPoint = new IPEndPoint(IPAddress.Parse(serverIP), 5000); //服务器地址
_client = new UdpClient();//不指定端口,系统自动分配

_userList = new UserCollection();
_listenThread = new Thread(new ThreadStart(Run));
}

/// <summary>
/// 获取服务器IP,INI文件内设置
/// </summary>
/// <returns></returns>
private string GetServerIP()
{
string file = Application.StartupPath + "\\ip.ini";
string ip = File.ReadAllText(file);
return ip.Trim();
}

/// <summary>
/// 启动客户端
/// </summary>
public void Start()
{
if (this._listenThread.ThreadState == ThreadState.Unstarted)
{
this._listenThread.Start();
}
}

/// <summary>
/// 客户登录
/// </summary>
///
string ip = "";
public void Login(string userName, string password)
{
_client.Connect(_hostPoint);
ip = password;
_LocalUserName = userName;

MessageEntity messageEntity = new MessageEntity();
messageEntity.NickName = userName;
messageEntity.MessageType = MessagePicks.OnLine;
messageEntity.MessageContent = string.Empty; ;
this.SendMessage(messageEntity, _hostPoint);

}

/// <summary>
/// 登出
/// </summary>
public void Logout()
{
//C2S_LogoutMessage lgoutMsg = new C2S_LogoutMessage(_LocalUserName);
//this.SendMessage(lgoutMsg, _hostPoint);

//this.Dispose();
//System.Environment.Exit(0);
}

/// <summary>
/// 发送请求获取用户列表
/// </summary>
public void DownloadUserList()
{
//C2S_GetUsersMessage getUserMsg = new C2S_GetUsersMessage(_LocalUserName);
//this.SendMessage(getUserMsg, _hostPoint);
}

/// <summary>
/// 显示在线用户
/// </summary>
/// <param name="users"></param>
private void DisplayUsers(UserCollection users)
{
if (_UserChangedHandle != null)
(_UserChangedHandle.Target as Control).Invoke(_UserChangedHandle, users);
}

/// <summary>
/// 通话请求
/// </summary>
/// <param name="users"></param>
private void Call(string friend)
{
if (_CallChangedHandle != null)
(_CallChangedHandle.Target as Control).Invoke(_CallChangedHandle, friend);
}

/// <summary>
/// 接受通话请求
/// </summary>
/// <param name="users"></param>
private void ReceiveCall(string friend,string accept)
{
if (receiveCallChangedHandle != null)
(receiveCallChangedHandle.Target as Control).Invoke(receiveCallChangedHandle, friend,accept);
}
/// <summary>
/// 接受视频
/// </summary>
/// <param name="users"></param>
private void ReceivePic(byte[] pic)
{
if (_receivePicChangedHandle != null)
(_receivePicChangedHandle.Target as Control).Invoke(_receivePicChangedHandle, pic);
}
private void ReceiveAudio(byte[] aud)
{
if (_receiveAudioChangedHandle != null)
(_receiveAudioChangedHandle.Target as Control).Invoke(_receiveAudioChangedHandle, aud);
}
private void ReceiveFile(byte[] file)
{
if (_receiveFileChangedHandle != null)
(_receiveFileChangedHandle.Target as Control).Invoke(_receiveFileChangedHandle, file);
}
private void ReceiveDraw(List<List<Pointt>> drawPoints,int whetherReceive3d)
{
if (_receiveDrawChangedHandle != null)
(_receiveDrawChangedHandle.Target as Control).Invoke(_receiveDrawChangedHandle, drawPoints, whetherReceive3d);
}
private void ReceiveScreenSize(float width,float height)
{
if (_receiveScreenSizeChangedHandle != null)
(_receiveScreenSizeChangedHandle.Target as Control).Invoke(_receiveScreenSizeChangedHandle, width, height);
}
public string MidStrEx(string sourse, string startstr, string endstr)
{
string result = string.Empty;
int startindex, endindex;
try
{
startindex = sourse.IndexOf(startstr);
if (startindex == -1)
return result;
string tmpstr = sourse.Substring(startindex + startstr.Length);
endindex = tmpstr.IndexOf(endstr);
if (endindex == -1)
return result;
result = tmpstr.Remove(endindex);
}
catch (Exception ex)
{

}
return result;
}

//运行线程
private int m_intBlockLength = 1000; //每一个数据包的大小
byte[] data = new byte[20000];
byte[] dataVioce = new byte[20000];
private void Run()
{
try
{
byte[] buffer;
int i = 0;
int j = 0;
int i_voice = 0;
int j_voice = 0;
while (true)
{
try
{
buffer = _client.Receive(ref _remotePoint);//_remotePoint变量返回当前连接的用户IP地址

int des = 0;
if (buffer[2] == 0x10 && buffer[3] == 0x10)

{
i = buffer[1];

8000
int c = buffer[0];

if (i==0 && data[0]>0)
{
try
{
byte[] vediobyte = data.Skip(11).Take(data.Length).ToArray();
ReceivePic(vediobyte);
//buffer = null;

}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
j = 0;
}
}

//之前的包
if (buffer[0] != buffer[1] + 1)
{
Array.Copy(buffer, 4, data, i * (m_intBlockLength), m_intBlockLength); //复制数据

if(i>j)
{
continue;
}
j += 1;
if (j > c | j == c)
{
j = i + 1;
}

}
else
{
//最后一个包
int packesize = buffer[4] * 256 + buffer[5];
Array.Copy(buffer, 6, data, i * (m_intBlockLength), packesize); //复制数据 最后一个包 data.Length-packesize
j += 1;
if (j > c)
{
j = c;
}

}

//if (buffer[0] == j)
//{
//    j = 0;
//    try
//    {
//        byte[] vediobyte = data.Skip(11).Take(data.Length).ToArray();
//        ReceivePic(vediobyte);
//        //buffer = null;

//    }
//    catch (Exception ex)
//    {
//        MessageBox.Show(ex.ToString());
//        j = 0;
//    }
//}
des = 1;

}
if (buffer[2] == 0x10 && buffer[3] == 0x11)
{
des = 1;

i_voice = buffer[1];
int c = buffer[0];

if (i_voice == 0 && dataVioce[0] > 0)
{
try
{

byte[] bytelen = new byte[4];
bytelen[0] = dataVioce[11];
bytelen[1] = dataVioce[12];
bytelen[2] = dataVioce[13];
bytelen[3] = dataVioce[14];
int len = BitConverter.ToInt32(bytelen, 0);
byte[] audiobyte = dataVioce.Skip(15).Take(len).ToArray();
ReceiveAudio(audiobyte);
DoWriteLog("收到语音数据长度" + buffer.Length);

}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
j_voice = 0;
}
}

//之前的包
if (buffer[0] != buffer[1] + 1)
{
Array.Copy(buffer, 4, dataVioce, i_voice * (m_intBlockLength), m_intBlockLength); //复制数据

if (i_voice > j_voice)
{
continue;
}
j_voice += 1;
if (j_voice > c | j_voice == c)
{
j_voice = i_voice + 1;
}

}
else
{
//最后一个包
int packesize = buffer[4] * 256 + buffer[5];
Array.Copy(buffer, 6, dataVioce, i_voice * (m_intBlockLength), packesize); //复制数据 最后一个包 data.Length-packesize
j_voice += 1;
if (j_voice > c)
{
j_voice = c;
}

}

}
if (buffer[2] == 0x10 && buffer[3] == 0x13)
{

}
if (des == 0)
{
string str = System.Text.Encoding.UTF8.GetString(buffer);
string ss = MidStrEx(str, "$", "*");
MessageEntity entity = (MessageEntity)JsonConvert.DeserializeObject<MessageEntity>(ss);
AnalysisPackage(entity, null);
}
}
catch (Exception ex)
{
//buffer=null;
//i = 0;
j = 0;
}

}
}
catch (Exception ex) { DoWriteLog(ex.Message); }
}

#region 接收服务器返回的包并分析处理

private void AnalysisPackage(MessageEntity entity, User user)
{
try
{

switch (entity.MessageType)
{
case MessagePicks.OnLine:
if (entity.MessageContentEx.Count > 0)
{

_userList.Clear();

foreach (KeyValuePair<string, string> kvp in entity.MessageContentEx as Dictionary<string, string>)
{
ListViewItem lvi = new ListViewItem();
lvi.Text = kvp.Key;
lvi.Tag = kvp.Value;
User a = new User(kvp.Key, null);
_userList.Add(a);

this.DisplayUsers(_userList);
}
}
break;
case MessagePicks.Message:

DoWriteLog(entity.MessageContent);
//   txtMessage.Append(entity.NickName + "【" + entity.RemoteEndPoint + "】 say:\n" + entity.MessageContent);
break;
case MessagePicks.OffLine:

break;
case MessagePicks.Vedio:

byte[] bytes = entity.receiveClientVideoBytes;
ReceivePic(bytes);

break;
case MessagePicks.FileOnLine:

byte[] filebytes = entity.receiveClientVideoBytes;
ReceiveFile(filebytes);

break;
case MessagePicks.AcceptVedio:

if (entity.MessageContent.ToString() == "1") //对方已接听 ,开始发视频语音流
{
ReceiveCall(entity.NickName,"1");

}
else if (entity.MessageContent.ToString() == "0") //对方拒绝接听
{
ReceiveCall(entity.NickName,"0");
}

break;
case MessagePicks.RequestVedio: //对方是否接听
this.Call(entity.NickName);

break;
case MessagePicks.Draw:
ReceiveDraw(entity.drawPoints, 1);
break;
case MessagePicks.ScreenHeightWidth:
ReceiveScreenSize((float)entity.VedioWidth, (float)entity.VedioHeight);
break;
default:

break;
}
}
catch (Exception ex)
{

}

}
#endregion

#region IDisposable 成员

public void Dispose()
{
try
{
this._listenThread.Abort();
this._client.Close();
}
catch
{

}
}

#endregion

public void SendMessage(MessageEntity msg, IPEndPoint remoteIP)
{
if (msg == null) return;
// DoWriteLog("正在发送消息给->" + remoteIP.ToString() + ",内容:" + msg.ToString());
string msgJson = JsonConvert.SerializeObject(msg, Formatting.None);

byte[] buffer = System.Text.Encoding.UTF8.GetBytes("$" + msgJson + "*");

_client.Send(buffer, buffer.Length);
DoWriteLog("消息已发送.");
}
public byte[] copybyte(byte[] a, byte[] b)
{
byte[] c = new byte[a.Length + b.Length];
a.CopyTo(c, 0);
b.CopyTo(c, a.Length);
return c;
}
public void SendBufferMessage(byte[] msg, IPEndPoint remoteIP)
{

_client.Send(msg, msg.Length);

}

public void SendMediaMessage(MessageEntity msg, IPEndPoint remoteIP)
{
if (msg == null) return;

byte[] username = new byte[9];
//username = System.Text.Encoding.UTF8.GetBytes(msg.receiveClient);
for (int i = 0; i < System.Text.Encoding.UTF8.GetBytes(msg.receiveClient).Length; i++)
{
username[i] = System.Text.Encoding.UTF8.GetBytes(msg.receiveClient)[i];
}
byte[] result = new byte[msg.receiveClientVideoBytes.Length + 2 + username.Length];

byte[] b = new byte[2];
b[0] = 0x10;
b[1] = 0x10;

result = copybyte(b, username);
result = copybyte(result, msg.receiveClientVideoBytes);

_client.Send(result, result.Length);
DoWriteLog("消息已发送.");
}
public void SendAudioMessage(MessageEntity msg, IPEndPoint remoteIP)
{
if (msg == null) return;
byte[] username = new byte[9];
//username = System.Text.Encoding.UTF8.GetBytes(msg.receiveClient);
for (int i = 0; i < System.Text.Encoding.UTF8.GetBytes(msg.receiveClient).Length; i++)
{
username[i] = System.Text.Encoding.UTF8.GetBytes(msg.receiveClient)[i];
}
byte[] result = new byte[msg.receiveClientVideoBytes.Length + 2 + username.Length];

byte[] b = new byte[2];
b[0] = 0x10;
b[1] = 0x11;

result = copybyte(b, username);

byte[] lenData = new byte[4];
for (int i = 0; i < BitConverter.GetBytes(msg.receiveClientVideoBytes.Length).Length; i++)
{
lenData[i] = BitConverter.GetBytes(msg.receiveClientVideoBytes.Length)[i];
}

BitConverter.GetBytes(msg.receiveClientVideoBytes.Length);
result = copybyte(result, lenData);
result = copybyte(result, msg.receiveClientVideoBytes);

_client.Send(result, result.Length);
DoWriteLog("消息已发送.");
}

}

}


如果有需要源码可以找我,800块钱一套
微信:zhengzujoe

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: