| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 786 人关注过本帖
标题:p2p 通信问题
只看楼主 加入收藏
ruidi
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2014-7-29
结帖率:0
收藏
已结贴  问题点数:20 回复次数:1 
p2p 通信问题
大家好:我是个小菜鸟,刚刚接触网络编程,老师要求我们写一个视频聊天和文件发送的程序。我根据网络应用编程的书上改写了一份,但是中间很多问题:
(1)文件传输和视频聊天的不能同时进行;
(2)视频聊天时候,开启调试,视频刚打开就关上了;
(3)双方视频聊天时候有一方不能接收视频,只能发送视频。
求路过的大神帮忙,解决一下啊!
源码:using System;
using System.Collections.Generic;
using
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using
using
using
using
using System.Drawing.Imaging;
using System.Windows.Media.Imaging;

namespace sheji
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
           this.FormBorderStyle = FormBorderStyle.FixedSingle;
        this.MaximizeBox = false;
        registerAndResolve();
        udpChat = new UdpChat(this);
        }
        /************摄像头****************/
    WebCamera myCamera = new WebCamera(); //摄像头对象
    int device_number = 0;   //摄像头编号
    bool bLocalShow = false;  //是否正在预览
    bool bCallRemote = false;  //是否进行视频呼叫
    IDataObject data;
    Image bmap;
    /************对等通信用*************/
    //自定义对等点名称
    String strpeerName = "Myp2pVedio";
    TcpListener listener;
    TcpClient localclient;
    User user;
    BinaryWriter localbw;
    BinaryReader localbr;
    NetworkStream localsr;
    String remotePort = "";
    String remoteIP = "";
    Thread thredRece;  //接收视频信息
    Thread thredListen;//接受连接请求
    MemoryStream receiveMS;//保存一帧图片
    int receiveLength;//一帧图片的长度
    bool isExit = false;//是否停止接收视频信息
    UdpChat udpChat;//发送聊天信息
    List<ListViewItem> resolvedListViewItem = new List<ListViewItem>();
    int i = 0;//表示选定的视频源
   
   
    private void registerAndResolve()
    {
        getPort();
        //将本应用使用的IP地址及端口号,注册到群中
        if (!MyPNRP.registerPeer(strpeerName))
            MessageBox.Show("未开启点对点服务");
        //定期解析对等点所在群的同名对等节点的信息
        Thread resolveThread = new Thread(Resolve);
        resolveThread.Start();
        resolveThread.IsBackground = true;
        Start_Receiving_Video_Conference();
        startrecefile();
    }
    /// <summary>
    /// 获取一个可用端口号,启动监听
    /// </summary>
    public void getPort()
    {
        while (true)
        {
            //设置本应用使用的端口号
            MyPNRP.port = new Random().Next(50000, 51000);
            try
            {
                listener = new TcpListener(IPAddress.Any, MyPNRP.port);
                listener.Start();
            }
            catch
            {
                continue;
            }
            break;
        }
    }
    /// <summary>
    /// 解析名称
    /// </summary>
    private void Resolve()
    {
        while (!isExit)
        {
            PeerNameRecordCollection recColl = MyPNRP.ResolverPeer(strpeerName);
            resolvedListViewItem.Clear();
            foreach (PeerNameRecord record in recColl)
            {
                foreach (IPEndPoint endP in record.EndPointCollection)
                {
                    if (endP.AddressFamily.Equals(AddressFamily.InterNetwork))
                    {
                        ListViewItem item1 = new ListViewItem(endP.ToString());
                        resolvedListViewItem.Add(item1);
                    }
                }
            }
            //检查是否有其他终端退出,如已经退出则从列表中删除该项
            if (resolvedListViewItem.Count == 0)
                ClearItems();
            else
                RemoveItem();
            foreach (PeerNameRecord record in recColl)
            {
                foreach (IPEndPoint endP in record.EndPointCollection)
                {
                    if (endP.AddressFamily.Equals(AddressFamily.InterNetwork))
                    {
                        ListViewItem item1 = new ListViewItem(endP.ToString());
                        AppendItem(item1);
                    }
                }
            }
        }
    }

        private void Form1_Load(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            string name = Dns.GetHostName();
            IPHostEntry localip = Dns.GetHostEntry(name);
            listBox1.Items.Add("本机ip:");
            
            foreach (IPAddress ip in localip.AddressList)
            {
                listBox1.Items.Add(ip);
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            this.textBox2.Text = "";
        }

        private void button4_Click(object sender, EventArgs e)
        {
            try
            {
                remoteIP = listView1.SelectedItems[0].ToString().Split(':')[1];
                remoteIP = remoteIP.Substring(2, remoteIP.Length - 2);
                udpChat.sendData(remoteIP, remotePort, this.textBox2.Text);
               
            }
            catch
            {
                MessageBox.Show("请选择正确接收方");
            }
        }
        private void text_keypress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                remoteIP = listView1.SelectedItems[0].ToString().Split(':')[1];
                remoteIP = remoteIP.Substring(2, remoteIP.Length - 2);
                udpChat.sendData(remoteIP, remotePort, this.textBox2.Text);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //呼叫视频请求
            if (!bCallRemote)
            {
                try
                {
                    remotePort = this.listView1.SelectedItems[0].ToString().Split(':')[2].Substring(0, 5);
                    remoteIP = listView1.SelectedItems[0].ToString().Split(':')[1];
                    remoteIP = remoteIP.Substring(2, remoteIP.Length - 2);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                    MessageBox.Show("未选择远程主机");
                    return;
                }
                if (bLocalShow == false && Start_Sending_Video_Conference())
                {
                    if (LocalVedioShow())
                    {
                        bLocalShow = true;
                        this.button2.Text = "取消预览";
                    }
                }

            }
            else
            {
                label1.Text = "视频中断";
                if (localclient != null)
                {
                    try
                    {
                        timersend.Stop();
                        button2_Click(null, null);
                        localbw.Write("stop:false");
                        localclient.Close();
                        localbw.Close();
                        localsr.Close();
                        localbr.Close();


                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                }
                this.button1.Text = "视频呼叫";
                bCallRemote = false;
            }

        }
        /// <summary>
        /// 开始发送数据
        /// </summary>
        private bool Start_Sending_Video_Conference()
        {
            try
            {
                localclient = new TcpClient(remoteIP, int.Parse(remotePort));//Connecting with server
                localsr = localclient.GetStream();
                localbw = new BinaryWriter(localsr);
                localbr = new BinaryReader(localsr);
                localbw.Write("Query:false");
                if (localbr.ReadString() == "OK:false")
                {
                    timersend.Enabled = true;
                    timersend.Start();
                    label1.Text = "开始视频发送";
                    this.button1.Text = "中断视频";
                    bCallRemote = true;
                    return true;
                }
                else
                {
                    this.button1.Text = "视频呼叫";
                    label1.Text = "远程主机未对视频请求做出响应";
                    localbw.Close();
                    localbr.Close();
                    return false;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                this.button1.Text = "视频呼叫";
                label1.Text = "远程主机未对视频请求做出响应";
                return false;
            }
        }
        /// <summary>
        /// 准备接收视频
        /// </summary>
        private void Start_Receiving_Video_Conference()
        {
            thredListen = new Thread(ReceiveConnect); // Start Thread Session
            thredListen.Start();
            thredListen.IsBackground = true;
        }
        /// <summary>
        /// 接收连接请求
        /// </summary>
        private void ReceiveConnect()
        {
            while (!isExit)
            {
                TcpClient remoteClient = listener.AcceptTcpClient();
                isExit = false;
                user = new User(remoteClient);
                thredRece = new Thread(ReceiveMessage);
                thredRece.IsBackground = true;
                thredRece.Start(user);
            }
        }
        /// <summary>
        /// 接收信息
        /// </summary>
        private void ReceiveMessage(Object myUser)
        {
            User user = (User)myUser;
            while (!isExit)
            {
                //保存接收的命令字符串
                string receiveString = null;
                //解析命令用
                //每条命令均带有一个参数,值为true或者false,表示是否有紧跟的字节数组
                string[] splitString = null;
                byte[] receiveBytes = null;
                try
                {
                    //从网络流中读出命令字符串
                    //此方法会自动判断字符串长度前缀,并根据长度前缀读出字符串
                    receiveString = user.br.ReadString();
                    splitString = receiveString.Split(':');
                    if (splitString[1] == "true")
                    {
                        //先从网络流中读出32位的长度前缀
                        receiveLength = user.br.ReadInt32();
                        //然后读出指定长度的内容保存到字节数组中
                        receiveBytes = user.br.ReadBytes(receiveLength);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                    //this.pictureBoxFriend.Image = (System.Drawing.Image)Resources.ResourceManager.GetObject("vedio");
                    //底层套接字不存在时会出现异常
                    SetlabelTips("接收数据失败");
                    break;
                }
                if (receiveString == null)
                {
                    if (isExit == false)
                    {
                        //this.pictureBoxFriend.Image = (System.Drawing.Image)Resources.ResourceManager.GetObject("vedio");
                        SetlabelTips("接收数据失败");
                    }
                    break;
                }
                SetlabelTips("收到:" + receiveString);
                switch (splitString[0])
                {
                    case "Query":
                        //询问是否接受视频请求
                        if (MessageBox.Show(String.Format("接收{0}视频请求", user.remoteClient.Client.RemoteEndPoint), "消息", MessageBoxButtons.YesNo) == DialogResult.Yes)
                        {
                            user.bw.Write("OK:false");
                        }
                        else
                            user.bw.Write("NO:false");
                        break;
                    case "Image":
                        //传递图片
                        try
                        {
                            //利用接收到得字节数组创建内存流
                            receiveMS = new MemoryStream(receiveBytes);
                            //从流中获取图片
                            this.pictureBox1.Image = Image.FromStream(receiveMS);
                            //关闭内存流
                            receiveMS.Close();
                            //清空内存流
                            receiveMS.Flush();
                            //重置内存流
                            receiveMS = null;
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("接收图片错误");
                            Console.WriteLine(ex.ToString());
                            break;
                        }
                        break;
                    case "Stop":
                        //停止接收视频
                        //this.pictureBoxFriend.Image = (System.Drawing.Image)Resources.ResourceManager.GetObject("vedio");
                        isExit = true;
                        break;
                    default:
                        break;
                }
            }
        }
        private bool LocalVedioShow()
        {
            //设定设备信息
            myCamera.IDevice = device_number;
            //开始在本地预览显示
            if (!myCamera.OpenPreviewWindow(this.pictureBox2))
            {
                MessageBox.Show("视频预览失败!请检查摄像头设备是否连接正常,驱动是否安装!");
                return false;
            }
            return true;
        }
      
        /// <summary>
        /// 发送视频数据
        /// </summary>
        private void Send_One_Capture(BinaryWriter bw)
        {
            //将字节数组存放到内存流中
            MemoryStream ms = new MemoryStream();
            try
            {
                //将摄像头的一帧数据存放到剪贴板中
                myCamera.CaptureWindow();
                //从剪贴板中获取图片
                data = Clipboard.GetDataObject();
                //将截图存放到内存流中
                if (data.GetDataPresent(typeof(System.Drawing.Bitmap)))
                {
                    bmap = ((Image)(data.GetData(typeof(System.Drawing.Bitmap))));
                    bmap.Save(ms, ImageFormat.Bmp);
                }
                //将截图以JPEG形式保存到内存流中
                this.pictureBox2.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                //从流中获取字节数组
                byte[] arrImage = ms.GetBuffer();
                bw.Write("Image:true");
                //写入数据长度
                bw.Write(arrImage.Length);
                //发送图片
                bw.Write(arrImage);
                ms.Flush();
                bw.Flush();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                button1_Click (null, null);
                bw.Close();
            }
            ms.Close();
        }
        private void timersend_Tick_1(object sender, EventArgs e)
        {
            Send_One_Capture(localbw);
        }
        
        /// <summary>
        /// 多线程访问控件
        /// </summary>
        /// <param name="item"></param>
        delegate void AppendItemDelegate(ListViewItem item);
        public void AppendItem(ListViewItem item)
        {
            if (listView1.InvokeRequired)
            {
                AppendItemDelegate d = AppendItem;
                listView1.Invoke(d, item);
            }
            else
            {
                Boolean exist = false;
                foreach (ListViewItem myitem in listView1.Items)
                {
                    if (myitem.Text.Equals(item.Text))
                    {
                        exist = true;
                    }
                }
                if (!exist)
                    listView1.Items.Add(item);
            }
        }
        /// <summary>
        /// 删除已经推出对等点的ListItem项
        /// </summary>
        delegate void RemoveItemDelegate();
        public void RemoveItem()
        {
            if (listView1.InvokeRequired)
            {
                RemoveItemDelegate d = RemoveItem;
                listView1.Invoke(d);
            }
            else
            {
                bool exist;
                foreach (ListViewItem itemUser in listView1.Items)
                {
                    exist = false;
                    foreach (ListViewItem itemResolveNew in resolvedListViewItem)
                    {
                        if (itemUser.Text.Equals(itemResolveNew.Text))
                        {
                            exist = true;
                            break;
                        }
                    }
                    if (!exist)
                        listView1.Items.Remove(itemUser);
                }
            }
        }
        /// <summary>
        /// 清空所有ListItem项
        /// </summary>
        delegate void ClearItemDelegate();
        public void ClearItems()
        {
            if (listView1.InvokeRequired)
            {
                ClearItemDelegate d = ClearItems;
                listView1.Invoke(d);
            }
            else
            {
                listView1.Items.Clear();
            }
        }
        /// <summary>
        /// 清空发送框
        /// </summary>
        delegate void ClearRichTextBoxSendDelegate();
        public void ClearRichTextBox()
        {
            if (this.textBox2.InvokeRequired)
            {
                ClearRichTextBoxSendDelegate d = ClearRichTextBox;
                textBox2.Invoke(d);
            }
            else
            {
                textBox2.Clear();
                textBox2.Focus();
            }
        }
        delegate void SetRichTextBoxReceiveDelegate(String text);
        public void SetRichTextBoxReceive(String text)
        {
            if (this.textBox2.InvokeRequired)
            {
                SetRichTextBoxReceiveDelegate d = SetRichTextBoxReceive;
                this.textBox1.Invoke(d, text);
            }
            else
            {
                textBox1.AppendText(text);
                textBox1.AppendText(Environment.NewLine);
            }
        }
        delegate void SetlabelTipsDelegate(String text);
        public void SetlabelTips(String text)
        {
            if (this.label1.InvokeRequired)
            {
                SetlabelTipsDelegate d = SetlabelTips;
                this.label1.Invoke(d, text);
            }
            else
            {
                label1.Text = text;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //开始预览
            if (bLocalShow == false)
            {
                if (LocalVedioShow())
                {
                    bLocalShow = true;
                    this.button2.Text = "取消预览";
                }
            }
            else
            {
                myCamera.ClosePreviewWindow();
                bLocalShow = false;
                this.button2.Text = "本地预览";
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (bLocalShow == true)
            {
              if(i==1)
              {
                  
                  
                  //给对方拍照
              
              }
              else
              {
              
                    myCamera.CaptureWindow();
                    data = Clipboard.GetDataObject();
                    if (data.GetDataPresent(typeof(Bitmap)))
                    {
                        bmap = (Image)data.GetData(typeof(Bitmap));
                        string savefile = @"D:\" + DateTime.Now.ToFileTime().ToString()+".jpg" ;
                        bmap.Save(savefile, ImageFormat.Jpeg);
                    }
              }

            }
            else
            {
                MessageBox.Show("请选择视频源");
            }
        }
        //关闭窗体
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            isExit = true;
            if (timersend.Enabled)
            {
                timersend.Stop();
                timersend.Enabled = false;
            }
            if (localclient != null)
            {
                if (localclient.Connected)
                    localclient.Close();
            }
            if (user != null)
            {
                user.remoteClient.Close();
                user.br.Close();
                user.bw.Close();
            }
            myCamera.ClosePreviewWindow();
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            i = 1;
        }
      /////////文件操作////////
        private int size = 66530000;
        private void filesend()
        {
            string strpath = "";
            int num = 0;
            DialogResult result;
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.InitialDirectory = @"C:\";
            dlg.Filter = "图片(*.jpg,*.gif.*.bmp)|*.jpg,*.gif,*.bmp|文本文件(*.txt)|*.txt|All Files(*.*)|(*.*)";
            result = dlg.ShowDialog();
            strpath = dlg.FileName;
            try
            {
                remotePort = this.listView1.SelectedItems[0].ToString().Split(':')[2].Substring(0, 5);
                remoteIP = listView1.SelectedItems[0].ToString().Split(':')[1];
                remoteIP = remoteIP.Substring(2, remoteIP.Length - 2);
                TcpClient client = new TcpClient(remoteIP, int.Parse(remotePort));//连接远程服务器
                NetworkStream ns = client.GetStream();//获取网络流
               BinaryReader lbr = new BinaryReader(ns);
               BinaryWriter  lbw = new BinaryWriter(ns);
                if (result == DialogResult.OK)
                {
                    lbw.Write("ready:false");//写入准备(即发送文件前的询问 )
                    if (lbr.ReadString() == "ok")//如果从网络中读取(即对方发送的是ok)
                    {
                        
                        FileStream fs = new FileStream(strpath, FileMode.Open, FileAccess.Read);
                        double ld = fs.Length;
                        while (ld > 0 && ns.CanWrite)
                        {
                            byte[] bytes = new byte[size];
                            num = fs.Read(bytes, 0, bytes.Length);
                            ns.Write(bytes, 0, num);
                            ld -= num;
                            label1.Text = "文件发送中...";

                        }
                        fs.Close();
                        ns.Close();
                        localbw.Close();
                        MessageBox.Show("文件发送完成");
                        label2.Text = "文件发送提示";
                    }
                    else
                    {
                        MessageBox.Show("对方拒绝接收");
                    }

                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            try
            {
                filesend();
            }
            catch
            {
                MessageBox.Show("请选择正确的主机");
            }
        }
        private void receviefile(object myuse)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            User user = (User)myuse;
            string receivestring = null;
            string[] splitstring = null;
            receivestring = user.br.ReadString();
            splitstring = receivestring.Split(':');
            switch (splitstring[0])
            {
                case "ready":
                    if (MessageBox.Show(String.Format("接收{0}文件", user.remoteClient.Client.RemoteEndPoint), "消息", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        user.bw.Write("ok");
                        try
                        {
                            int num = 0;
                            int len = 0;
                            if (user.stream != null)
                            {
                                SaveFileDialog sfd = new SaveFileDialog();
                                sfd.Filter = "所有文件|*.txt";
                                if (sfd.ShowDialog(this) == DialogResult.OK)
                                {
                                    string filesavepath = sfd.FileName;
                                    FileStream fm = new FileStream(filesavepath, FileMode.Create, FileAccess.Write);
                                    byte[] buffer = new byte[512];
                                    while ((num = user.stream.Read(buffer, 0, buffer.Length)) > 0)
                                    {
                                        fm.Write(buffer, 0, num);
                                        len += num;
                                    }
                                    fm.Close();
                                    user.stream.Close();
                                    MessageBox.Show("文件接收完成!");
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            MessageBox.Show(e.Message);
                        }
                        break;
                    }
                    else
                    {
                        user.bw.Write("no");
                    }
                    break;

                default:
                    break;

            }

        }
        private void startrecefile()
        {
            Thread thredlisten = new Thread(receconnect);
            thredlisten.Start();
            thredlisten.IsBackground = true;
        }
        private void receconnect()
        {
            TcpClient remoteclient = listener.AcceptTcpClient();
            user = new User(remoteclient);
            Thread th = new Thread(receviefile);
            th.IsBackground = true;
            th.Start(user);
        }


        



      
        
    }
}
搜索更多相关主题的帖子: 网络编程 视频聊天 网络应用 通信 
2014-07-29 19:32
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:20 
代码太 长了  没耐性看完

感觉问题和多线程有关  先复习一下多线程的相关知识吧

DO IT YOURSELF !
2014-07-30 16:32
快速回复:p2p 通信问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.025871 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved