c# 端口监听问题

wuzhicheng5 2010-01-12 06:23:15
c# 端口监听主要有两重方式:

1. TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 2000);
server.Start();

while(true)
{
TcpClient client = server.AcceptTcpClient();//开始监听
NetworkStream ns = client.GetStream(); //创建网络流,进行读写
}

2. IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), int.Parse("2000"));
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(ipep);
server.Listen(10);
while(true)
{
Socket client = server.Accept();//开始监听
NetworkStream ns = new NetworkStream(client);//创建网络流,进行读写
}

问题:
根据上面两种方式,都会在收取完一次数据包后,断开连接,进行下一次监听时,若有新连接,再创建连接,获取数据包。
我的需求是,能不能实时的监听端口,同时不要频繁的新建连接断开连接?

期待大侠!
...全文
3413 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
LiaoAn_Sun 2012-02-07
  • 打赏
  • 举报
回复
谢谢,我也遇到这样的问题。现在我看了都不用花分啦
ssf193 2011-12-06
  • 打赏
  • 举报
回复
我也不知道,求指教啊~
zqs1002 2011-10-11
  • 打赏
  • 举报
回复
明天试一下
LIMINLY520 2011-07-19
  • 打赏
  • 举报
回复
可以在取苏拘留的时候创建一个线程来读取数据
ChinaBruceHe 2011-06-24
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 walkghost 的回复:]

引用 17 楼 wuzhicheng5 的回复:
感谢walkghost,我结贴了,我采用了你的思路,暂时把一断一连的问题解决了。

不客气。多写几次通信程序就行了。我也是初学者,写了几次就慢慢的熟悉多了。而且我的方法肯定不是最优的。或者你可以试试异步通信,只不过对异步的我还没研究过。
[/Quote]

很赞成你说的!顶一下~
walkghost 2010-01-14
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 wuzhicheng5 的回复:]
感谢walkghost,我结贴了,我采用了你的思路,暂时把一断一连的问题解决了。
[/Quote]
不客气。多写几次通信程序就行了。我也是初学者,写了几次就慢慢的熟悉多了。而且我的方法肯定不是最优的。或者你可以试试异步通信,只不过对异步的我还没研究过。
wuzhicheng5 2010-01-14
  • 打赏
  • 举报
回复
感谢walkghost,我结贴了,我采用了你的思路,暂时把一断一连的问题解决了。
  • 打赏
  • 举报
回复
这东西太难了 搞不明白
walkghost 2010-01-13
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 wuzhicheng5 的回复:]
感谢walkghost,我正在研读你的代码,看我是否能使上,如有不明之处,我会继续跟帖,请留意新信息。

再次感谢。


ck11926375 朋友你好,如今采用的就是你所说的方式,所以请阅读下我的需求,期望再次跟帖。
[/Quote]
不客气,你需要启动多个线程。
wuzhicheng5 2010-01-13
  • 打赏
  • 举报
回复
回复 walkghost

1.能把DTUClient 类文件代码贴出来吗,我想尝试你这样的写法,所以我想看看你是怎么封装的和读取的

2.请问你用NetworkStream ns 读写数据时,读写完毕后ns要关闭吗?好像ns关闭了,连接也会断掉,不知道你会不会。

期待答复!谢谢。
th_temp 2010-01-13
  • 打赏
  • 举报
回复
学习
wuzhicheng5 2010-01-13
  • 打赏
  • 举报
回复
感谢walkghost,我正在研读你的代码,看我是否能使上,如有不明之处,我会继续跟帖,请留意新信息。

再次感谢。


ck11926375 朋友你好,如今采用的就是你所说的方式,所以请阅读下我的需求,期望再次跟帖。
walkghost 2010-01-13
  • 打赏
  • 举报
回复
上面的回帖中:
if (_tmpdtuclient.DTUTCPClient == null)
break;
这个应该去掉。

呃,这是我实际项目中的通信部分代码,因为不涉及商业问题,所以我给贴出来了。
ck11926375 2010-01-13
  • 打赏
  • 举报
回复

private void StartListen()
{
this.TcpListener = new TcpListener(19808);
this.TcpListener.Start();
while( true )
{
TcpClient TcpClient = this.TcpListener.AcceptTcpClient();
NetworkStream MyStream = TcpClient.GetStream();
byte [] bytes = new byte[2048];
int bytesRead = MyStream.Read(bytes,0,bytes.Length);
string message = System.Text.Encoding.UTF8.GetString(bytes,0,bytesRead);
}
}

private void MainForm_Load(object sender, System.EventArgs e)
{
this.Listener = new Thread(new ThreadStart(StartListen));
this.Listener.Start();
}

walkghost 2010-01-13
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wuzhicheng5 的回复:]
回复  walkghost,非常感谢你的答复。但是问题没有解决。

1.举例说1000个包只是想表达我想在一次连接中接受多个包,只要客户端一直连着,就是在一次连接中,而不是每接收一个包就断一次。

2.你用的TcpClient ClientTCPClient = _TCPListen.AcceptTcpClient(); 也即是我常用的,我的也是后台线程执行监听。监听操作就是通过上面这条语句停在那里,等待下次连接,但是你有没发现,每执行该条语句后就会断开连接,因为ClientTCPClient 被重新赋值了,而其实呢,客户端一直连着的,但也不得不随着服务端的断开而再次尝试新的连接从而发送下一个数据包。反复下去,就会频繁的一断一连。

3.我的希望是一次连接,可以发任意数目的数据包,直到客户端自行断开。

[/Quote]
1:同步阻止模式下的socket连接,在新到来一个连接的时候,你应当可以这样写:

while(true)
{
//TcpClient client = server.AcceptTcpClient();//开始监听
//NetworkStream ns = client.GetStream(); //创建网络流,进行读写
TcpClient ClientTCPClient = _TCPListen.AcceptTcpClient();
Thread ReadClientConnectThread = new Thread(new ParameterizedThreadStart(ReadClientDataThreadFun));//用于处理客户端连接的线程,
DTUClient _tmpdtuclient = new DTUClient(ClientTCPClient);//我自己定义的类,里面包含TCPClient和NetworkStream
ReadClientConnectThread.Start(_tmpdtuclient);//启动线程的时候把这个对象传进去
}
//处理客户端连接的函数:
/// <summary>
/// 接收客户端发送的数据的线程的目标函数
/// </summary>
protected void ReadClientDataThreadFun(object obj)
{
DTUClient _tmpdtuclient = (DTUClient)obj;

SetMSG("客户端已经连接,客户端信息:" + _tmpdtuclient.DTUTCPClient.Client.RemoteEndPoint.ToString());
int i = 0;
Thread.Sleep(50);
if (_tmpdtuclient.DTUTCPClient == null)
break;
int _readBytesCount = -1;//收到的数据的字节长度
byte[] _receiveBuffer = new byte[512];//接收缓冲区

while (true)
{
try
{
if (i == 0)
{
//如果是第一包数据,则可以断定是发送的手机号等信息
_readBytesCount = _tmpdtuclient.DTUNetworkStream.Read(_receiveBuffer, 0, _receiveBuffer.Length);//如果客户端断开了连接,则read方法会立即返回0
if (_readBytesCount == 0)
{
//客户端退出连接。
SetMSG("客户端退出连接!客户端信息:" + _tmpdtuclient.DTUTCPClient.Client.RemoteEndPoint.ToString());
Thread.CurrentThread.Abort();
}
else
{
//
string _ReceiveDataStr = string.Empty;
_ReceiveDataStr = Encoding.Default.GetString(_receiveBuffer, 0, _readBytesCount);
}
i++;
}//发送的手机号等DTU身份信息
else
{
//下位机响应上位机命令执行后回传的数据,这里是接收
if (_readBytesCount == 0)
{
//客户端退出连接。
SetMSG("客户端退出连接!客户端信息:" + _tmpdtuclient.DTUTCPClient.Client.RemoteEndPoint.ToString());
Thread.CurrentThread.Abort();
}
else
{
SetMSG("收到:" + NomalFunction.ByteArrayToHexString(_receiveBuffer, _readBytesCount)+" ("+Encoding.Default.GetString(_receiveBuffer,0,_readBytesCount)+" ) 收到字节数:" + _readBytesCount.ToString());

}
}

Thread.Sleep(50);
}
catch (ThreadAbortException thae)
{
dtuClientList.Remove(_tmpdtuclient);
_tmpdtuclient.Close();
SetMSG("现在还有" + dtuClientList.Count.ToString() + "个连接。");
break;
}
catch (Exception ex)
{
SetMSG("读取客户端发送的数据时出错!详细信息:" + ex.Message);
dtuClientList.Remove(_tmpdtuclient);
_tmpdtuclient.Close();
SetMSG("现在还有" + dtuClientList.Count.ToString() + "个连接。");
break;
}
Thread.Sleep(5000);
}
_tmpdtuclient.Close();
}

wuzhicheng5 2010-01-13
  • 打赏
  • 举报
回复
回复 walkghost,非常感谢你的答复。但是问题没有解决。

1.举例说1000个包只是想表达我想在一次连接中接受多个包,只要客户端一直连着,就是在一次连接中,而不是每接收一个包就断一次。

2.你用的TcpClient ClientTCPClient = _TCPListen.AcceptTcpClient(); 也即是我常用的,我的也是后台线程执行监听。监听操作就是通过上面这条语句停在那里,等待下次连接,但是你有没发现,每执行该条语句后就会断开连接,因为ClientTCPClient 被重新赋值了,而其实呢,客户端一直连着的,但也不得不随着服务端的断开而再次尝试新的连接从而发送下一个数据包。反复下去,就会频繁的一断一连。

3.我的希望是一次连接,可以发任意数目的数据包,直到客户端自行断开。
walkghost 2010-01-12
  • 打赏
  • 举报
回复

情况是这样的,客户端向服务器端请求一个连接,连接成功后,客户端每隔1分钟向服务器端发送1个数据包,期间不断开连接,总共1000个数据包,即1000分钟后,连接才关闭。TCP机制是可以实现的,但我查遍了很多资料,c#中服务器端都是每收取一次包,就断开。
=====================================
这个你就需要自己加一个标识了。判断总共收到了每个客户端多少个数据包,当数据包达到1000后,主动关闭networkStream.结束线程。
注意:要为每个连接保存一个“已经收到的数据包的Count”的标识,每收到一包,解析完毕后要把这个标识自增一次。
walkghost 2010-01-12
  • 打赏
  • 举报
回复
补充问题:

在客户端建立连接但没发送数据包时,服务器端能判断出与客户端连接上了吗?
=================================================
TCPListener.AcceptTCPClient()方法是阻塞的,所以,当客户端连接上来的时候,就可以在这个方法后新开的超线程的目标函数里断定新客户端已经连接。
walkghost 2010-01-12
  • 打赏
  • 举报
回复
问题:
根据上面两种方式,都会在收取完一次数据包后,断开连接,进行下一次监听时,若有新连接,再创建连接,获取数据包。
我的需求是,能不能实时的监听端口,同时不要频繁的新建连接断开连接?

期待大侠!
==============================
如果你是用的多线程的话,除非你手动断开连接或者客户端断开连接,连接会一直存在。
多线程的逻辑大概如下:


//初始化TcpListener
//启动一个新的线程,假定该线程的目标函数是ThreadATargetFun(object _TcpListener)
//线程启动的时候要把TCPListener传递到目标函数中。
//在该函数中:
//先把object强制转换成TCPListener
_TcpListener.Start()
while(true)
{
TcpClient ClientTCPClient = _TCPListen.AcceptTcpClient();
Thread ReadClientConnectThread = new Thread(new ParameterizedThreadStart(ReadClientDataThreadFun)); //ReadClientDataThreadFun(object ClientTCPClient)
ReadClientConnectThread.Start(_tmpdtuclient);//传递该客户端
}

/// <summary>
/// 接收客户端发送的数据的线程的目标函数
/// </summary>
protected void ReadClientDataThreadFun(object obj)
{
//要增加自己的try、catch模块,判断是否客户端断开连接,或者网络中断等故障
//
//强制转换成TCPClient,获取网络流
while(true)
{
int _readBytesCount = -1;
byte[] _receiveBuffer = new byte[512];
_readBytesCount = _tmpdtuclient.DTUNetworkStream.Read(_receiveBuffer, 0, _receiveBuffer.Length);//如果客户端断开了连接,则read方法会立即返回0
if (_readBytesCount == 0)
{
//客户端退出连接。
SetMSG("客户端退出连接!客户端信息:" + _tmpdtuclient.DTUTCPClient.Client.RemoteEndPoint.ToString());
Thread.CurrentThread.Abort();
}
//读写网络流
}
}


wuzhicheng5 2010-01-12
  • 打赏
  • 举报
回复
非常感谢2楼的朋友xray2005

情况是这样的,客户端向服务器端请求一个连接,连接成功后,客户端每隔1分钟向服务器端发送1个数据包,期间不断开连接,总共1000个数据包,即1000分钟后,连接才关闭。TCP机制是可以实现的,但我查遍了很多资料,c#中服务器端都是每收取一次包,就断开。

着实郁闷!2楼的朋友,我应该就是要你所说的长连接,但烦请详细描述下,谢谢!
加载更多回复(3)

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧