问题描述
在服务器端用到while(true)循环读取客户端发来的数据,在accept方法之后用while(true)来循环读取客户端发送数据过来,断点发现只有客户端发数据过来才能进入这个循环,而且客户端发来的数据只有第一次是正确的,以后每次发来的数据在服务器端看都是第一次的数据,服务器代码如下usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Windows.Forms;usingSystem.Net.Sockets;usingSystem.Net;usingSystem.Threading;namespace_507NetChatServer{publicpartialclassForm1:Form{IPAddressHostIP;SocketAcceptSo,So;stringstr;byte[]mbyte=newbyte[1024];publicForm1(){InitializeComponent();}privatevoidForm1_Load(objectsender,EventArgse){Control.CheckForIllegalCrossThreadCalls=false;try{HostIP=IPAddress.Parse("192.168.1.114");IPEndPointpoint=newIPEndPoint(HostIP,Int32.Parse("16666"));//实例化Socket对象So=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);So.Bind(point);So.Listen(50);Threadthread=newThread(newThreadStart(process));thread.Start();}catch(Exceptionex){MessageBox.Show("连接时:"+ex.Message);}}privatevoidbutton1_Click(objectsender,EventArgse){}voidprocess(){AcceptSo=So.Accept();while(true){if(AcceptSo!=null&&AcceptSo.Connected==true){Array.Clear(mbyte,0,mbyte.Length);AcceptSo.Receive(mbyte,mbyte.Length,0);str+=Encoding.BigEndianUnicode.GetString(mbyte);this.richTextBox2.AppendText(str);}//AcceptSo.Close();}}privatevoidbutton2_Click(objectsender,EventArgse){try{Byte[]SendByte;stringSendStr=So.LocalEndPoint+":"+this.richTextBox1.Text+"";SendByte=Encoding.BigEndianUnicode.GetBytes(SendStr.ToCharArray());AcceptSo.Send(SendByte,SendByte.Length,0);}catch(Exceptionex){MessageBox.Show("发送时:"+ex.Message);}}privatevoidForm1_FormClosing(objectsender,FormClosingEventArgse){if(AcceptSo!=null&&AcceptSo.Connected==true){AcceptSo.Close();}if(So.Connected==true){So.Close();}}}}
解决方案
解决方案二:
voidprocess(){while(true){AcceptSo=So.Accept();if(AcceptSo!=null&&AcceptSo.Connected==true){Array.Clear(mbyte,0,mbyte.Length);AcceptSo.Receive(mbyte,mbyte.Length,0);str+=Encoding.BigEndianUnicode.GetString(mbyte);this.richTextBox2.AppendText(str);}//AcceptSo.Close();}}
解决方案三:
Receive的时候会返回字节数,如果是0表示连接要断开了.不能总使用整个mbyte来显示,因为填不满的时候会有前一次的数据残留.而且mbyte不能放在外层共用,要放在while(true)上这样每个连接的数据互不干扰.AcceptSo不能放在外层共用,新的连接会把前面的覆盖,前面的就丢了.
解决方案四:
AcceptSo=So.Accept();
主要是这句代码:为新建连接创建新的Socket,也就是只有连接上且有数据发过来,代码待会往下走,也就是走到你的while里去,就是这么设计的。
解决方案五:
引用3楼sudazf的回复:
AcceptSo=So.Accept();主要是这句代码:为新建连接创建新的Socket,也就是只有连接上且有数据发过来,代码待会往下走,也就是走到你的while里去,就是这么设计的。
这个时候假使我又有另一个客户端过来链接,或者我的客户端断开再链接,是不是就无法链接了?因为我的AcceptSo=So.Accept();在整个代码中就执行了一次。
解决方案六:
引用4楼zcguoji的回复:
Quote: 引用3楼sudazf的回复:
AcceptSo=So.Accept();主要是这句代码:为新建连接创建新的Socket,也就是只有连接上且有数据发过来,代码待会往下走,也就是走到你的while里去,就是这么设计的。
这个时候假使我又有另一个客户端过来链接,或者我的客户端断开再链接,是不是就无法链接了?因为我的AcceptSo=So.Accept();在整个代码中就执行了一次。
socket针对你的IP+port进行监听,换了客户端ip或者端口来连接,不执行重新绑定,肯定是无法连接了,网络断开肯定也不行了。