问题描述
这是从csdn上下载的代码。先上代码服务器端privatevoidForm1_Load(objectsender,EventArgse){Control.CheckForIllegalCrossThreadCalls=false;//不捕捉错误线程提示try{serverSokcet=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);IPAddressip=IPAddress.Any;serverinfo=newIPEndPoint(ip,port);serverSokcet.Bind(serverinfo);//绑定ip地址serverSokcet.Listen(30);//开始监听,并且挂期数为10mss=newbyte[65535];clientSocket=newSocket[65535];clientNum=0;//从0开始计数//创建一个线程serverThread=newThread(newThreadStart(recieveAccept));serverThread.Start();}catch{}}privatevoidrecieveAccept(){while(true){clientSocket[clientNum]=serverSokcet.Accept();}}#regionprivateIPEndPointserverinfo;//存放服务器ip和端口privateSocketserverSokcet;//服务器端运行的socketprivateThreadserverThread;//服务器运行的线程privateSocket[]clientSocket;//存放客户端运行的socketprivateintclientNum;//存放客户端数量privatebyte[]mss;//消息intport=316;#endregionprivatevoidbutton2_Click(objectsender,EventArgse){try{Thread.Sleep(350);mss=Encoding.Unicode.GetBytes("Send");clientSocket[0].Send(mss);clientSocket[0].BeginReceive(mss,0,mss.Length,SocketFlags.None,newAsyncCallback(RecieveCallBack),clientSocket[0]);}catch{}}privatevoidRecieveCallBack(IAsyncResultar){try{mss=newbyte[1048576];intnumber=clientSocket[0].Receive(mss);Imageimg=CaptureScreen.ToImage(mss);img=CaptureScreen.BySizeGetScreen(img,pictureBox1.Width,pictureBox1.Height);if(img!=null){pictureBox1.Image=img;}clientSocket[0].BeginReceive(mss,0,mss.Length,SocketFlags.None,newAsyncCallback(RecieveCallBack),clientSocket[0]);}catch{}}
客户端privatevoidForm1_Load(objectsender,EventArgse){_mss=newbyte[65536];CheckForIllegalCrossThreadCalls=false;//允许子线程刷新数据Threadt=newThread(go);t.IsBackground=true;t.Start();Threadt1=newThread(recieveAccept);t1.IsBackground=true;t1.Start();}IPEndPointserverInfo;SocketclinentSocket;publicvoidgo(){try{lock(this){clinentSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);serverInfo=newIPEndPoint(IPAddress.Parse("192.168.1.140"),316);clinentSocket.Connect(serverInfo);intrend=clinentSocket.Receive(_mss);stringmsg=Encoding.Unicode.GetString(_mss,0,rend);if(msg=="Send"){MessageBox.Show("send");_mss=newbyte[65535];_mss=newMonitor().GetDesktopBitmapBytes();if(clinentSocket.Connected){clinentSocket.Send(_mss);clinentSocket.BeginSend(_mss,0,_mss.Length,SocketFlags.None,newAsyncCallback(ReceiveCallBack),clinentSocket);}}}}catch{go();}}///<summary>///回调函数///</summary>///<paramname="ar"></param>protectedvoidReceiveCallBack(IAsyncResultar){try{Socketlistener=(Socket)ar.AsyncState;_mss=newMonitor().GetDesktopBitmapBytes();if(listener.Connected){listener.BeginSend(_mss,0,_mss.Length,SocketFlags.None,newAsyncCallback(ReceiveCallBack),listener);}}catch{go();}}
下面问题就是服务器端监控的窗口是弹出式的,当我关闭这个弹出窗体在打开的时候,就会报错,说通常每个套接字地址(协议/网络地址/端口)只允许使用一次。请求大神帮忙。
解决方案
解决方案二:
请教帮助。这是一个局域网监控的项目,服务器端可以观看每一个客户端的屏幕,而且客户端也可以观看服务器端的屏幕,当然客户端监控室由服务器端发起的。
解决方案三:
不要胡乱加什么弹出窗口你的服务端真正运行起来之后,必然是无人操作的,而不可能派个人整天盯着看是否有弹窗,弹出了就关闭所以你所有的测试都应该是基于无弹出的设计否则你现在即使让它不报错了,等你把弹出拿掉,还是需要从头测试
解决方案四:
你使用了线程,这个线程跟你的窗体是无关的窗体关闭了,但是线程还在执行你再次打开窗体,就又开了一个线程
解决方案五:
引用2楼Z65443344的回复:
不要胡乱加什么弹出窗口你的服务端真正运行起来之后,必然是无人操作的,而不可能派个人整天盯着看是否有弹窗,弹出了就关闭所以你所有的测试都应该是基于无弹出的设计否则你现在即使让它不报错了,等你把弹出拿掉,还是需要从头测试
我弹窗是测试那个发送文字的东西。测试了,第一次能够监控,但是第二次就报错了,稍等给你看错误提示。
解决方案六:
如果你使用异步发送,异步接收,异步侦听,而不是同步阻塞while死循环那么就根本不需要把这些代码丢进线程里主线程发送接收就可以了具体可以自己测试没必要用线程的地方乱用线程反而会引发许多诡异的问题
解决方案七:
引用3楼Z65443344的回复:
你使用了线程,这个线程跟你的窗体是无关的窗体关闭了,但是线程还在执行你再次打开窗体,就又开了一个线程
解决方案八:
引用5楼Z65443344的回复:
如果你使用异步发送,异步接收,异步侦听,而不是同步阻塞while死循环那么就根本不需要把这些代码丢进线程里主线程发送接收就可以了具体可以自己测试没必要用线程的地方乱用线程反而会引发许多诡异的问题
这是从网上摘来的代码,个人对线程还是不太熟练。我在试试。
解决方案九:
你已经有一个线程对某个端口进行侦听再开一个线程还对这个端口进行侦听,就会报错了具体原因就是你关闭窗体的时候线程并没有自动退出,你也没有写任何代码让线程退出
解决方案十:
你抄的例子里,人家应该是当个真正的服务端程序运行在服务器上的而不是你这样把服务端也作为一个客户端来用例子代码根本没考虑窗口会没事被关闭又重新打开
解决方案十一:
而且作为一个"服务端",侦听是不应该被关闭的,应该随时侦听客户端的连接请求只不过你需要控制客户端和服务端什么时候交换报文(发送接收)否则你某个窗体被关闭,所有客户端就都连接不上你的服务端了,你还控制啥
解决方案十二:
引用10楼Z65443344的回复:
而且作为一个"服务端",侦听是不应该被关闭的,应该随时侦听客户端的连接请求只不过你需要控制客户端和服务端什么时候交换报文(发送接收)否则你某个窗体被关闭,所有客户端就都连接不上你的服务端了,你还控制啥
本来想的是创建个单例的类,不知道这样是不是太占用资源了?一直让她处于监听状态。感谢大神了。
解决方案十三:
引用10楼Z65443344的回复:
而且作为一个"服务端",侦听是不应该被关闭的,应该随时侦听客户端的连接请求只不过你需要控制客户端和服务端什么时候交换报文(发送接收)否则你某个窗体被关闭,所有客户端就都连接不上你的服务端了,你还控制啥
privatevoidFrm_StudentScreenForm_FormClosed(objectsender,FormClosedEventArgse){msgBuffer=Encoding.Unicode.GetBytes("stop");clientSocket[0].Send(msgBuffer);//clientSocket[0].BeginReceive(msgBuffer,0,msgBuffer.Length,SocketFlags.None,newAsyncCallback(RecieveCallBack),clientSocket[0]);if(serverThread!=null)serverThread.Abort();//线程终止if(serverSocket!=null){//CloseSocket();serverSocket.Close();//关闭SOCKET}//if(clientSocket.Length>=0)//{//clientSocket=newSocket[65535];//}this.Dispose();}protectedvoidCloseSocket(){if(serverSocket.Connected){//禁用发送和接受serverSocket.Shutdown(SocketShutdown.Both);//关闭套接字,不允许重用serverSocket.Disconnect(false);serverSocket.Close();}}
线程也种植了啊
解决方案十四:
引用11楼qq_30425243的回复:
Quote: 引用10楼Z65443344的回复:
而且作为一个"服务端",侦听是不应该被关闭的,应该随时侦听客户端的连接请求只不过你需要控制客户端和服务端什么时候交换报文(发送接收)否则你某个窗体被关闭,所有客户端就都连接不上你的服务端了,你还控制啥本来想的是创建个单例的类,不知道这样是不是太占用资源了?一直让她处于监听状态。感谢大神了。
我觉得以你现在的需求,是把客户端和服务端弄反了被监控的那些电脑上跑的应该是服务端而监控电脑跑的是客户端这样你可以随时连接任何一个被监控机,也可以随时断开,而不必随时接收所有被监控电脑的数据
解决方案十五:
你开了2个线程,一个用来侦听,一个用来接收而你只终止了1个线程
解决方案:
最简单的办法当然是把侦听和接收放到一个线程里去有任何必要放2个线程在这里吗而且异步侦听,异步接收,都不阻塞代码而侦听,发送,接收,其实是很快的,根本不会阻塞UI所以这里根本没必要用线程
解决方案:
引用15楼Z65443344的回复:
最简单的办法当然是把侦听和接收放到一个线程里去有任何必要放2个线程在这里吗而且异步侦听,异步接收,都不阻塞代码而侦听,发送,接收,其实是很快的,根本不会阻塞UI所以这里根本没必要用线程
好的,我改改试试。线程的东西不太熟悉。
解决方案:
引用16楼qq_30425243的回复:
Quote: 引用15楼Z65443344的回复:
最简单的办法当然是把侦听和接收放到一个线程里去有任何必要放2个线程在这里吗而且异步侦听,异步接收,都不阻塞代码而侦听,发送,接收,其实是很快的,根本不会阻塞UI所以这里根本没必要用线程好的,我改改试试。线程的东西不太熟悉。
我觉得你把客户端和服务端倒过来,就简单的多.既然所有控制都是在一台机器上,那么这台机器作为客户端去主动连接另外多台机器,这样多方便.不需要控制的机器,还去接收它的数据作甚
解决方案:
引用17楼Z65443344的回复:
Quote: 引用16楼qq_30425243的回复:
Quote: 引用15楼Z65443344的回复:
最简单的办法当然是把侦听和接收放到一个线程里去有任何必要放2个线程在这里吗而且异步侦听,异步接收,都不阻塞代码而侦听,发送,接收,其实是很快的,根本不会阻塞UI所以这里根本没必要用线程好的,我改改试试。线程的东西不太熟悉。
我觉得你把客户端和服务端倒过来,就简单的多.既然所有控制都是在一台机器上,那么这台机器作为客户端去主动连接另外多台机器,这样多方便.不需要控制的机器,还去接收它的数据作甚
然后客户端也需要观看服务器的屏幕,就是教师讲课把屏幕让学生看,服务器也能监控学生的屏幕。
解决方案:
哦.明白了.其实你改为UDP可能更简单一些.UDP可以广播.这样你就不用把数据循环的往所有客户端发送.