c# socket服务serverSocket.Accept();卡死问题

梅小梅 2016-05-27 02:58:44
public class MvcApplication : System.Web.HttpApplication
{
private static int myProt = 4502; //socket监听端口
static Thread listenThread;
private static Boolean isConSocket = false;
//日志打印,需要引入log4net,log4net.xml配置存放日志的位置。
private static log4net.ILog Log = LogManager.GetLogger("MvcApplication");
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

RouteConfig.RegisterRoutes(RouteTable.Routes);

//启动socket服务。
StartSocketByConfig();
Thread.Sleep(2000);
//监听socket服务。
Thread socketListen = new Thread(ListenSocketService);
socketListen.Start();
}

public static void StartSocketByConfig()
{
listenThread = new Thread(ListenConnect);
listenThread.Start();
}

/// <summary>
/// 监听客户端连接
/// </summary>
private static void ListenConnect()
{
//socket服务器IP地址
IPAddress ipAddress = IPAddress.Parse("192.168.3.141");//绑定IP地址:端口
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, myProt);
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//设置KeeyAlive,如果客户端不主动发消息时,Tcp本身会发一个心跳包,来通知服务器,这是一个保持通讯的链接。
//避免等到下一次通讯时,才知道链接已经断开。
serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);

serverSocket.Bind(localEndPoint);
Log.Debug(String.Format("启动监听{0}成功\n", serverSocket.LocalEndPoint.ToString()));
serverSocket.Listen(1); //设定最多1个排队连接请求

isConSocket = true;
Log.Debug("ListenConnect 开始"+ isConSocket);
Socket socket = null;
int i = 0;
while (true && isConSocket)
{
try
{
//接收连接
if(serverSocket == null)
{
continue;
}
socket = serverSocket.Accept(); //服务第一次启动时,是正常的;因为异常断开后,通过监听线程再次启动服务后,就卡死在这边,不报异常,也不接收客户端。 请问是什么原因呢?
socket.ReceiveTimeout = 500;
//接收的数据
StateObject state = new StateObject();
if (socket.Available > 0)
{
socket.Blocking = true;
int bytesRead = socket.Receive(state.buffer, 0, state.buffer.Length, SocketFlags.None);
read(state.buffer, bytesRead);
socket.Shutdown(SocketShutdown.Receive);
}

socket.Close();
socket.Dispose();
}
catch (Exception ex)
{
Log.Debug("ListenConnect 监听异常!");
Log.Debug("ListenConnect===" + ex.ToString(), ex);
try
{
if(socket != null)
{
Log.Debug("ListenConnect socket!");
// socket.Disconnect(false);
socket.Close();
socket.Dispose();
}
if(serverSocket != null)
{
Log.Debug("ListenConnect serverSocket!");
// serverSocket.Disconnect(false);
serverSocket.Close();
serverSocket.Dispose();
}
}
catch(Exception e)
{
Log.Debug("ListenConnect 222监听异常!",e);
}
finally
{
isConSocket = false;
socket = null;
serverSocket = null;
}
}
finally
{
Thread.Sleep(20);
}
}
Log.Debug("ListenConnect 结束"+ isConSocket);
}

public static void read(byte[] buffer, int bytesRead)
{
try
{
if (bytesRead > 0)
{
//接收的数据
StringBuilder sb = new StringBuilder();
sb.Append(Encoding.ASCII.GetString(buffer, 0, bytesRead));
string content = sb.ToString();
if (content.IndexOf("\r\n") > -1 || content.IndexOf("<EOF>") > -1 || content.IndexOf("\0") > -1)
{
//从百傲瑞达系统接收到的开关门实时事件。
try
{
//businessMethod(content);//业务逻辑
}
catch (Exception ex)
{
Log.Debug(String.Format("业务逻辑消息异常{0}", ex.Message));
}
Log.Debug(String.Format("接收客户端的消息{0}", content));
}
}
}
catch (Exception ex)
{
Log.Debug("接收客户端的消息异常.");
Log.Debug("ReadCallback===" + ex.ToString());
}
}

void Application_End(object sender, EventArgs e)
{
listenThread.Abort();
isConSocket = false;
}

void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
listenThread.Abort();
}

/// <summary>
/// 监听服务是否正常,socket服务断开则重启
/// </summary>
private static void ListenSocketService()
{
while (true)
{
try
{
if ( !isConSocket) //IsSocketConnected(serverSocket) &&
{
Log.Debug("socket 服务重新启动\n");
listenThread.Abort();
StartSocketByConfig();
}
}
catch (Exception ex)
{
Log.Debug("socket 服务启动异常\n");
Log.Debug("ListenSocketService===" + ex.ToString());
}
Thread.Sleep(100);
}
}
///
/// 判断connected的方法,但未检测对端网线断开或ungraceful的情况
///
public static bool IsSocketConnected(Socket s)
{
return (s == null || !s.Connected);
}
}

public class StateObject
{
//client socket
public Socket workSocket = null;
//接收的长度
public const int BufferSize = 1024 * 50;
//接收的数据
public byte[] buffer = new byte[BufferSize];
//接收的数据
public StringBuilder sb = new StringBuilder();
}
}
...全文
1447 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
楼主,是怎么解决的呢,求指教
我爱AI 2019-07-22
  • 打赏
  • 举报
回复
serverSocket.Accept(); 就一直卡住,是阻塞监听的方式
超人吉助 2016-10-10
  • 打赏
  • 举报
回复
引用 9 楼 wml_wu 的回复:
终于搞定了……
怎么搞定的,我也是刚学socket,能否指点一下啊
uu11231207 2021-07-08
  • 举报
回复
@超人吉助 有没有大佬具体说一下,好久了。解决不了,还有while怎么保持等待连接的状态
梅小梅 2016-05-27
  • 打赏
  • 举报
回复
终于搞定了……
梅小梅 2016-05-27
  • 打赏
  • 举报
回复
引用 7 楼 songbing774933 的回复:
如果你要刚开始学些socket,这样写没问题,可以基本理解sokect的原理 但是如果你是要用这个来做具体的项目的话,是不行的。 你要学会用异步和事件来处理客户端接入,数据收发。 而不是一味的在那while、sleep。
最近开始用socket的,流程大概是明白的,但是一到实际应用中,发现这么写,总是达不到要求,serverSocket.Accept(); 就一直卡住
songbing774933 2016-05-27
  • 打赏
  • 举报
回复
如果你要刚开始学些socket,这样写没问题,可以基本理解sokect的原理

但是如果你是要用这个来做具体的项目的话,是不行的。
你要学会用异步和事件来处理客户端接入,数据收发。
而不是一味的在那while、sleep。
楚狂歌 2016-05-27
  • 打赏
  • 举报
回复
引用 5 楼 wml_wu 的回复:
[quote=引用 4 楼 u011266608 的回复:] ‘’因为异常断开后,通过监听线程再次启动服务后“ 1、异常断开....这个作为服务端遇到异常也不能让他断开吧/ 2、异常后while (true && isConSocket)的这个判断, isConSocket重置没? 3、 socket = serverSocket.Accept()最好每个连接客户端都开一个线程来处理
1. 异常后,是直接给close,再重新启动。 2. isConSocket 有重设了。 3. socket = serverSocket.Accept() 就卡在这儿了,也不会往下执行,所以有没有开一个线程来处理,是不是不重要了呢?[/quote] 那监视一下bind后serversokcet是不是正常的?我还是觉得就算异常也要让他继续跑而不是重新启动
梅小梅 2016-05-27
  • 打赏
  • 举报
回复
引用 4 楼 u011266608 的回复:
‘’因为异常断开后,通过监听线程再次启动服务后“ 1、异常断开....这个作为服务端遇到异常也不能让他断开吧/ 2、异常后while (true && isConSocket)的这个判断, isConSocket重置没? 3、 socket = serverSocket.Accept()最好每个连接客户端都开一个线程来处理
1. 异常后,是直接给close,再重新启动。 2. isConSocket 有重设了。 3. socket = serverSocket.Accept() 就卡在这儿了,也不会往下执行,所以有没有开一个线程来处理,是不是不重要了呢?
楚狂歌 2016-05-27
  • 打赏
  • 举报
回复
‘’因为异常断开后,通过监听线程再次启动服务后“ 1、异常断开....这个作为服务端遇到异常也不能让他断开吧/ 2、异常后while (true && isConSocket)的这个判断, isConSocket重置没? 3、 socket = serverSocket.Accept()最好每个连接客户端都开一个线程来处理
梅小梅 2016-05-27
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
删除 while语句、删除 sleep 语句,你就能够开始学习通讯服务程序设计了。 有 while语句的,基本上都是入门时的简单例子。而有sleep语句的,可以断定是坑人的代码。
去掉while , 那怎么使这个socket处于接收数据的状态呢? 没有sleep,CPU会飙高。 这个怎么解决?
  • 打赏
  • 举报
回复
删除 while语句、删除 sleep 语句,你就能够开始学习通讯服务程序设计了。 有 while语句的,基本上都是入门时的简单例子。而有sleep语句的,可以断定是坑人的代码。
梅小梅 2016-05-27
  • 打赏
  • 举报
回复
搞了好久了,求大神解答……

110,535

社区成员

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

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

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