关于TCP通信的问题,想请大家指点
首先,问题是这样的,我从网上COPY的代码已经可以实现客户端发送数据,服务器接收数据的基本功能,但是跟我理解的有点不同,我理解的TCP通信应该是服务器监听一个端口,一台客户端上线后,连接就建议,并与之通信,而监听的进程还在继续监听,但我总感觉实际不是这样,于是,有以下几个问题:
1.TcpListener可以用来监听,Socket也可以用来监听,两者有何区别。
2.如果用TcpListener监听,然后由Socket去处理,是不是TcpListener监听到之后就不在管了,剩下通信就是在Socket与客户端进行,好像打电话,TcpListener负责拨号,拨通了之后由Socket进行对话,TcpListener再去等待下一拨号。
求大家帮助,第一次接触TCP,问题可能有点弱,呵呵
从网上COPY一段代码如下:
1.窗体加载时启动监听线程:
this.tcpListener = new TcpListener(IPAddress.Any, 8899);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
2.监听线程里循环监听:
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
3.处理通信内容:
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
string result = Encoding.ASCII.GetString(message, 0, bytesRead);
Invoke(new UpdateDisplayDelegate(UpdateDisplay), new object[] { result });
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
}
tcpClient.Close();
}
[解决办法]
TcpListener就是对Socket的封装,它的功能最终还是通过socket执行的。
有些幼稚的人说:“哦,原来TcpListener内部最终还是通过Socket来执行的啊,那么说明Socket才是高级的啊”。这就本末倒置了。TcpListener之所以封装Socket,是有道理的,它更方便于完成高级的功能,更容易得到高效率,方便于程序设计师扩展到更高级应用层次。
[解决办法]
我不知道你从哪抄来的这个 HandleClientComm 方法。这是很烂的代码。我只挑最严重的说,实际上Tcp通讯是要“分包、且沾包”的。也就是说,就算你的buffer只有4096个字节,假设发送一个完整的命令是4000字节,第二个完整的命令是2000字节,那么服务器端可以第一次Read得到1800字节,第二次Read得到4096字节,第三次得到104个字节。
而这个仅仅“连续读取消息并执行Invoke”的程序完全不顾这种事实。完全不靠谱。
[解决办法]