如题.发送端和接收端同是C/S程序时,程序运行正常.但是当发送端仍是c/s版本,而把接收端改成b/s版本web程序的时候(代码除了把picturebox改成image控件,其他完全相似),接收端点击"接收"按钮时,提示错误:-------------------------------------------连接错误System.InvalidOperationException: 在执行此操作前必须先调用 Bind 方法。 在 System.Net.Sockets.Socket.Accept() 在 _Default.Button2_Click(Object sender, EventArgs e) 位置 c:\Inetpub\wwwroot\PicShow\Default.aspx.cs:行号 46 实际上我刚开始在"监听"按钮中已经监听了,已经bind了.C/S版本中就顺利通过了,为什么转换成B/S版本中就这样提示呢.如果再次bind,系统会提示"套接字端口只能使用一次什么的".现帖出接收端代码如下:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;using System.Drawing;
using System.Text;
using System.Net;
using System.IO;
using System.Net.Sockets;
using System.Drawing.Imaging;public partial class _Default : System.Web.UI.Page 
{
    System.Net.Sockets.Socket receivesocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
    //设置接收数据的地址
      System.Net.IPEndPoint hostipendpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Any,8080);      protected void Page_Load(object sender, EventArgs e)
    {
        if (!this.IsPostBack)
        {
            
        }

    }
 /// <summary>
    /// 监听
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Button1_Click(object sender, EventArgs e)
    {
        receivesocket.Bind(hostipendpoint);
        //监听
        receivesocket.Listen(2);
        this.Label1.Text = "已经开始监听";       
    }
   
 //连接
    protected void Button2_Click(object sender, EventArgs e)
    {
        try
        {
           
            //设置接收数据缓冲区的大小 
            byte[] b = new byte[1024 * 4];   //1024* 4
         
            System.Net.Sockets.Socket hostsocket = receivesocket.Accept();
            //如何确定该数组大小 
            System.IO.MemoryStream fs = new System.IO.MemoryStream();            int got = 0;
            int datalength = 0;            while (true)
            {
                got = hostsocket.Receive(b);
                fs.Write(b, 0, got);
                if (got > 0)
                    datalength = datalength + got;
                else
                    break;
            }
            Bitmap Img = new Bitmap(fs);           
            Img.Save("e:\\新建文件夹\\MyJpeg.jpg", ImageFormat.Jpeg);
             this.Image1.ImageUrl = @"e:\MyJpeg.jpg"; 
            //关闭写文件流
            fs.Close();
            //关闭接收数据的Socket 
            hostsocket.Shutdown(System.Net.Sockets.SocketShutdown.Receive);
            hostsocket.Close();         
            this.Response.Write("传输成功!");        }
        catch (Exception se)
        {
           this.Response.Write("连接错误" +se.ToString());
            return;
        }                      
    }
   }

解决方案 »

  1.   

    CS的程序,变量会一直存在,直到窗口关闭而BS的不一样,可能就在运行那几毫秒的时候存在,然后就没有了
      

  2.   

    楼主首先去搞清楚下WEB页面的加载和WEB页面上button按钮的POST过程我这里简单说下:
    你的button1按钮点击里Bind Socket,这个时候确实bind上了,点button2的时候,页面需要重新加载,
    因此你在页面级别定义变量的代码:
    System.Net.Sockets.Socket receivesocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); 
    又被执行了一次,那么这个新的recervesocket是不是会bind呢?答案是不会!因此就会提示你 连接错误System.InvalidOperationException: 在执行此操作前必须先调用 Bind 方法为什么你在button2里再次bind会报错呢?
    因为你前面一次的对象bind了端口8080,没有释放,因此你再次bind就会提示 “套接字端口只能使用一次什么的”看完我的介绍你再去调试下代码,把断点下在 
    System.Net.Sockets.Socket receivesocket = new XXXX 这里
      

  3.   

    简单的解决办法:
    System.Net.Sockets.Socket receivesocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); 
    改为:System.Net.Sockets.Socket receivesocket = null;在page_load里:
            if (!this.IsPostBack) 
            { 
                receivesocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
            }然后你在调试下程序,这个方法可以是你的程序可用,但个人认为不是好的解决方案好的解决方案应该是在WEB服务器上写一个服务去取数据,WEB只负责数据的展示
    WEB端用异步的方式解决取数据和显示上的时间差,比如出现一个loading...,
      

  4.   

    谢谢楼上,当把 
    System.Net.Sockets.Socket receivesocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); 
    改为:System.Net.Sockets.Socket receivesocket = null; 在page_load里: 
            if (!this.IsPostBack) 
            { 
                receivesocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); 
            } 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    这样改过以后,在点击"监听"按钮的时候,出现下列提示:
    未将对象引用设置到对象的实例。 
    说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 异常详细信息: System.NullReferenceException: 未将对象引用设置到对象的实例。源错误: 
    行 84:     protected void Button1_Click(object sender, EventArgs e)
    行 85:     {
    行 86:         receivesocket.Bind(hostipendpoint);
    行 87:         //监听
    行 88:         receivesocket.Listen(2);
     
      

  5.   

    不好意思,确实会出这个错
    因为页面加载的时候receivesocket被置NULL了改改:public System.Net.Sockets.Socket receivesocket
    {
        get{
             return (System.Net.Sockets.Socket)Session["receivesocket"];
            }
        set
        {
           Session["receivesocket"] = value;
    }
    }page_load里:
            if (!this.IsPostBack) 
            { 
                receivesocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); 
            }
      

  6.   

    因为页面加载的时候receivesocket被置NULL了是button1点击的时候页面重新加载,再次变为null,跟前面说的道理一样
      

  7.   

    楼上,谢谢,我改了,但是在连接的时候依然提示要在"System.Net.Sockets.Socket hostsocket = receivesocket.Accept();  "前面bind,我就在他前面bind了,也listen(2)了(同监听代码),系统又提示"套接字端口只能使用一次"
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    改过的代码如下:
    public partial class _Default : System.Web.UI.Page 
    {
       public System.Net.Sockets.Socket receivesocket
        {
            get
            {
                return (System.Net.Sockets.Socket)Session["receivesocket"];
            }
            set
            {
                Session["receivesocket"] = value;
            }
        } 
        //设置接收数据的地址 
        System.Net.IPEndPoint hostipendpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Any,8888);      protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                receivesocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); 
            }

        }    /// <summary>
        /// 监听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button1_Click(object sender, EventArgs e)
        {
            receivesocket.Bind(hostipendpoint);
            //监听
            receivesocket.Listen(2);
            this.Label1.Text = "已经开始监听";
        }
       
     //连接
        protected void Button2_Click(object sender, EventArgs e)
        {
            try
            {
             
                //设置接收数据缓冲区的大小 
                byte[] b = new byte[1024 * 4];   //1024* 4
                System.Net.Sockets.Socket hostsocket = receivesocket.Accept();       -----------------------------------------改后依然提示要"bind"
                //如何确定该数组大小 
                System.IO.MemoryStream fs = new System.IO.MemoryStream();            int got = 0;
                int datalength = 0;            while (true)
                {
                    got = hostsocket.Receive(b);
                    fs.Write(b, 0, got);
                    if (got > 0)
                        datalength = datalength + got;
                    else
                        break;
                }
                Bitmap Img = new Bitmap(fs);           
                Img.Save("e:\\新建文件夹\\MyJpeg.jpg", ImageFormat.Jpeg);
                 this.Image1.ImageUrl = @"e:\MyJpeg.jpg"; 
                //关闭写文件流
                fs.Close();
                //关闭接收数据的Socket 
                hostsocket.Shutdown(System.Net.Sockets.SocketShutdown.Receive);
                hostsocket.Close();         
                this.Response.Write("传输成功!");        }
            catch (Exception se)
            {
               this.Response.Write("连接错误" +se.ToString());
                return;
            }                      
        }
      
    }
      

  8.   

    好的,是不是我的连接这块//连接 
        protected void Button2_Click(object sender, EventArgs e) 
        { 
            try 
            { 
            
                //设置接收数据缓冲区的大小 
                byte[] b = new byte[1024 * 4];  //1024* 4 
                System.Net.Sockets.Socket hostsocket = receivesocket.Accept();      -----------------------------------------改后依然提示要"bind" 
                //如何确定该数组大小 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    这地方写的少了什么或者多了什么呀
      

  9.   

    直接在web中使用socket的方法不好,建议做一个activex,在里面实现你想要的功能
      

  10.   

    汗,楼主你啥环境?
    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;using System.Net.Sockets;
    using System.Net;public partial class Default4 : System.Web.UI.Page
    {    private Socket recs
        {
            get
            {
                return (Socket)Session["resc"];
            }
            set
            {
                Session["resc"] = value;
            }
        }    private IPEndPoint hostip = new IPEndPoint(IPAddress.Any, 8083);    protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                recs = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            }
        }
        protected void button1_Click(object sender, EventArgs e)
        {
            recs.Bind(hostip);
            recs.Listen(2);
        }
        protected void Button2_Click(object sender, EventArgs e)
        {
            try
            {
                Socket newscr = recs.Accept();
                Response.Write("accepted");
            }
            catch (System.Exception ex)
            {
                Response.Write(ex.Message);
            }
        }
    }
    我的代码测试通过,一切正常
    VS2005 + WINXP
      

  11.   

    我的环境跟楼上一样VS2005 + WINXP
      

  12.   

    楼上,这是我的客户端代码:我的程序顺序是: 监听-----连接-----截屏------接收.using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    namespace Example023_屏幕捕获程序
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
           
            ///   <summary>   
            ///   应用程序的主入口点。   
            ///   </summary>   
           
            [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
            private static extern bool BitBlt(
            IntPtr hdcDest,   //目标设备的句柄   
            int nXDest,   //   目标对象的左上角的X坐标   
            int nYDest,   //   目标对象的左上角的X坐标   
            int nWidth,   //   目标对象的矩形的宽度   
            int nHeight,   //   目标对象的矩形的长度   
            IntPtr hdcSrc,   //   源设备的句柄   
            int nXSrc,   //   源对象的左上角的X坐标   
            int nYSrc,   //   源对象的左上角的X坐标   
            System.Int32 dwRop   //   光栅的操作值   
            );        [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
            private static extern IntPtr CreateDC(
            string lpszDriver,   //   驱动名称   
            string lpszDevice,   //   设备名称   
            string lpszOutput,   //   无用,可以设定位"NULL"   
            IntPtr lpInitData   //   任意的打印机数据   
            );        System.Net.Sockets.Socket sendsocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
            //实例化socket 
            System.Net.IPEndPoint ipendpiont = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("192.168.1.100"),8083);  //服务器的IP和端口//因为客户端只是用来向特定的服务器发送信息,所以不需要绑定本机的IP和端口。不需要监听。
            private void button2_Click(object sender, EventArgs e)
            {           // sendsocket.Connect(ipendpiont);
                try
                {
                   sendsocket.Connect(ipendpiont);
                   MessageBox.Show("连接成功!");
            
                }
                catch (Exception se)
                {
                    MessageBox.Show("连接错误" + se.Message, "提示信息", MessageBoxButtons.RetryCancel, MessageBoxIcon.Information);
                    return;
                }  
            }        private void button1_Click(object sender, EventArgs e)
            {
                try
                {
                    this.Hide();
                    IntPtr dc1 = CreateDC("DISPLAY", null, null, (IntPtr)null);
                    //创建显示器的DC   
                    Graphics g1 = Graphics.FromHdc(dc1);
                    //由一个指定设备的句柄创建一个新的Graphics对象 
                    Bitmap MyImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, g1);
                    //根据屏幕大小创建一个与之相同大小的Bitmap对象   
                    Graphics g2 = Graphics.FromImage(MyImage);
                    //获得屏幕的句柄   
                    IntPtr dc3 = g1.GetHdc();
                    //获得位图的句柄   
                    IntPtr dc2 = g2.GetHdc();
                    //把当前屏幕捕获到位图对象中   
                    BitBlt(dc2, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, dc3, 0, 0, 13369376);
                    //把当前屏幕拷贝到位图中   
                    g1.ReleaseHdc(dc3);
                    //释放屏幕句柄   
                    g2.ReleaseHdc(dc2);
                    //释放位图句柄   
                    MyImage.Save("d:\\新建文件夹\\MyJpeg.jpg", ImageFormat.Jpeg);  //当然你也可以根据自己的需要,把屏幕以其他图片的格式来保存,如果你想把图片保存为位图文件,可以把"ImageFormat.Jpeg"改换成"ImageFormat.Bmp";想把图片保存为Gif文件,就把"ImageFormat.Jpeg"改换成"ImageFormat.Gif"。你可以保存的文件类型大概有十多种,这里就不一一介绍了,当然你也要相应改变保存文件的后缀。
                    pictureBox1.Image = MyImage;
                    pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;   //本程序所用控件为1个按狃,一个panel,一个picturebox,其中panel的属性Autoscroll =true; picturebox的属性SizeMode =AutoSize; 然后只要改变pictureBox的大小,图象就会跟着改变大小,如果把这句去掉的话,就可以实现图象按panel滚动条移动而查看全图。                // MessageBox.Show("已经把当前屏幕保存到D:\\MyJpeg.jpg文件中!");
                    this.Show();
                    //***************************************************************************************开始使用socket发送文件*********************************************************//
                  
                    //建立终结点 
                    System.IO.MemoryStream Stream = new System.IO.MemoryStream();
                    pictureBox1.Image.Save(Stream, System.Drawing.Imaging.ImageFormat.Bmp);//存储为bmp图象
                  //  pictureBox1.Image.Save(Stream, System.Drawing.Imaging.ImageFormat.Jpeg);   //不想存储为bmp图象,想存储为jpeg图象
                    byte[] b = Stream.ToArray();                 
                    //连接远程计算机 
                    sendsocket.Send(b);
                    //发送                 Stream.Close();
                    sendsocket.Shutdown(System.Net.Sockets.SocketShutdown.Send);
                    //关闭发送连接 
                    sendsocket.Close();            //关闭本                 //***********************************************************************************************************end*******************************************************//            }
                catch (Exception ex)
                {
                    string s = ex.ToString();
                    return;
                }
               
            }        
            private void timer1_Tick(object sender, EventArgs e)
            {
                if (sendsocket.Connected)
                {
                    this.label1.Text= "连接成功";            }
            }
          
        }
    }
      

  13.   

    接收端代码:---------------------接收端发起监听---发送段连接----发送段截取屏幕发送----接收端接收
    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;using System.Drawing;
    using System.Text;
    using System.Net;
    using System.IO;
    using System.Net.Sockets;
    using System.Drawing.Imaging;public partial class _Default : System.Web.UI.Page 
    {
       private System.Net.Sockets.Socket receivesocket
        {
            get
            {
                return (System.Net.Sockets.Socket)Session["receivesocket"];
            }
            set
            {
                Session["receivesocket"] = value;
            }
        } 
        //设置接收数据的地址 
        private System.Net.IPEndPoint hostipendpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Any,8083);      protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                receivesocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); 
            }

        }    /// <summary>
        /// 监听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button1_Click(object sender, EventArgs e)
        {
            receivesocket.Bind(hostipendpoint);
            //监听
            receivesocket.Listen(2);
            this.Label1.Text = "已经开始监听";
        }
       
     //连接
        protected void Button2_Click(object sender, EventArgs e)
        {
            try
            {
             
                //设置接收数据缓冲区的大小 
                byte[] b = new byte[1024 * 4];   //1024* 4
                System.Net.Sockets.Socket hostsocket = receivesocket.Accept();
                //如何确定该数组大小 
                System.IO.MemoryStream fs = new System.IO.MemoryStream();            int got = 0;
                int datalength = 0;            while (true)
                {
                    got = hostsocket.Receive(b);
                    fs.Write(b, 0, got);
                    if (got > 0)
                        datalength = datalength + got;
                    else
                        break;
                }
                Bitmap Img = new Bitmap(fs);           
                Img.Save("e:\\新建文件夹\\MyJpeg.jpg", ImageFormat.Jpeg);
                 this.Image1.ImageUrl = @"e:\MyJpeg.jpg"; 
                //关闭写文件流
                fs.Close();
                //关闭接收数据的Socket 
                hostsocket.Shutdown(System.Net.Sockets.SocketShutdown.Receive);
                hostsocket.Close();         
                this.Response.Write("传输成功!");        }
            catch (Exception se)
            {
               this.Response.Write("连接错误" +se.ToString());
                return;
            }                      
        }
      
    }
      

  14.   

    WEB屏幕监控的啊
    先把你的核心调通吧,网络通信都没建设起来,搞啥都没用别管那么多外部代码,核心就是socket建立连接的过程嘛你帖那么长代码,看起来就头晕呢
      

  15.   

    接收端发起监听---发送段连接这个似乎很难理解理论上应该是发送端被动监听,接收端主动连接那就是说应该是web端去连接你的winform那里,而你的winform的socket处于监听状态...搞不清楚你的逻辑
      

  16.   

    我觉得楼上这个流程是对的但是这样有一个技术问题需要你解决比如我安装了客户端C,我的IP是192.168.0.2,因为客户端C是处于监听状态
    所以你的服务端能连接到C,并指挥C抓屏幕,传数据等但是问题就在这里,你如何获取我的IP地址并连接上来?局域网内这个没有一点问题,客户端C上报到服务器就好了
    但是,互联网上就不是那么简单了,有可能客户端C是在一个子网内部的,通过路由上网,
    这样的情况你是连接不上客户端C的当然,这个问题也是可以解决的,参考下P2P的原理