c# winform 音视频 文件传输

此程序分服务端以及客户端,服务端负责信息的中转,最终实现微信的效果,服务器可挂在公务,并做了心跳检测。
客户端只需要能上网既能实现点对点通讯
采用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(username))
                    {
                        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;
                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];
                        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

猜你喜欢

转载自blog.csdn.net/zhengzujoe/article/details/90446556