背景
今天在处理一个c#应用崩溃的问题的时候,发现这样一行调试信息。
“System.Net.Sockets.SocketException”类型的未经处理的异常在 System.dll 中发生
以一种访问权限不允许的方式做了一个访问套接字的尝试。
一、分析
- 出现这样的错误信息,我一直以为是我代码里的问题。(譬如说访问已经close的套接字)
- 后来查了一下,大家都说是换个端口。
- 换个端口,果然不崩溃了。但是我的程序却必须使用那个端口。
- 只能想点法子
二、确认问题所在
- 开始—->运行—->cmd,调出命令窗口
- 输入命令:netstat -ano,列出所有端口的情况。在列表中我们观察被占用的端口,我被占用的事3702
- 查看对应的进程PID,输入命令:netstat -aon|findstr “3702”,得到进程PID是 488
- 打开任务管理器,在进程PID那一列查看488对应的进程是哪个
- 发现果然是端口被某些系统服务占用了。
三、处理办法
- 第一种
这种方法是是像360那样子,把占用端口的程序杀掉。(这样子做会给用户带来麻烦,而且即使杀死了,用户去检查和处理起来反倒更麻烦) - 第二种
这种方法是,提醒用户去处理这个问题,不帮用户杀掉占用端口的程序。
以我的应用为例,我可以在用户打开我的程序的时候,提醒他端口被占用,然后换一个端口运行。但是,端口换掉可能会导致某些信息接收不到,需要把这个后果告诉用户,让用户自行处理。每次用户打开我的应用的时候,都检查一下,发现被占了,就提醒一次。直到用户解决完电脑或者设备上的冲突了,就不再显示这个问题了。
四、代码
下面贴一下检测端口占用的c#代码吧。
1. 第一种是利用c#的类库检测
#region 端口检测
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] udpEndPoints = properties.GetActiveUdpListeners();
if (udpEndPoints.Where(pp=>pp.Port == 3702).Count()>0)
{
MessageBox.Show(udpEndPoints.Where(pp => pp.Port == 3702).First().Address.ToString());
}
#endregion
- 第二种是利用netstat命令工具检测
#region 检测端口是否被占用
Process p = new Process();
p.StartInfo = new ProcessStartInfo("netstat", "-a");
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string result = p.StandardOutput.ReadToEnd().ToLower();
if (result.IndexOf(Environment.MachineName.ToLower() + ":3702") >= 0)
{
MessageBox.Show("端口被占用");
}
else
{
MessageBox.Show("ok");
}
#endregion
http://xzh.i3geek.com
1 条评论
lindexi · 2019年10月28日 17:53
多谢大佬