我在客户端,服务器端都使用同步socket,客户端正常发送消息没有问题,可以收到,如果客户端只是按了下 Enter 键,服务器端Receive函数就阻塞,不向下执行,客户端由于收不到服务器端返回的消息,也会阻塞。我的想法是在服务器端加个timer,如果3秒后,Receive函数没有执行完毕,就认为超时,然后给客户端发生超时消息,关闭本次Socket连接。但是掉用超时委托函数的时候,导致服务器端推出,请高人指教。
报异常信息为:一个封锁操作被对 WSACancelBlockingCall 的调用中断。
服务端代码
class Class1
{
public static bool flag=false; //函数Receive执行完毕 flag 置为 true
public static Socket temp=null; //接受的客户端连接
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
try
{
TimerCallback timerCallBack = new TimerCallback(ForeSendMsg);
int port =3001;
string ipstr="127.0.0.1";
IPAddress ip = IPAddress.Parse(ipstr);
IPEndPoint ipe = new IPEndPoint(ip,port);
Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
s.Bind(ipe);
s.Listen(50);
Console.WriteLine("begin listen ...." );
while(true)
{
flag = false;
temp=null;
temp = s.Accept();
string receStr;
byte[] receBytes = new byte[1024];
int bytes;
Console.WriteLine("start receive.........");
Timer timer = new Timer(timerCallBack,temp,3000,0); //设置定时器,3秒之后,如果Receive还没有执行完毕,认为超时,本次不再接受客户端数据,返回给客户端超时消息
bytes=temp.Receive(receBytes,0,receBytes.Length,SocketFlags.Partial);
flag=true;
Console.WriteLine("End receive............");
receStr = Encoding.GetEncoding("utf-8").GetString(receBytes,0,bytes);
Log.WriteLog("test",new StringBuilder(receStr+"\r\n"));
Console.WriteLine("receive msg="+receStr);
string sendstr = "ok!"+"dsssssssssssssss";
byte[] bs = Encoding.ASCII.GetBytes(sendstr);
temp.Send(bs,0,bs.Length,SocketFlags.None);
temp.Shutdown(SocketShutdown.Both);
temp.Close();
}
//s.Close();
}
catch(SocketException se)
{
Log.WriteLog("test",new StringBuilder(se.Message+"\r\n"));
Console.WriteLine("SocketException "+se.Message);
}
catch(Exception ex)
{
Log.WriteLog("test",new StringBuilder(ex.Message+"\r\n"));
Console.WriteLine("Exception "+ex.Message);
}
}
public static void ForeSendMsg(Object tmp)
{
Socket temp = (Socket)tmp;
if(temp!=null&&flag==false&&temp.Connected)
{
temp.Shutdown(SocketShutdown.Receive);
Console.WriteLine("Time is reach");
byte[] arr = Encoding.ASCII.GetBytes("Exception from 1");
temp.Send(arr);
temp.Shutdown(SocketShutdown.Both);
temp.Close();
}
}
}
客户端代码如下
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
// try
{
int port =3001;
string ipstr="127.0.0.1";
IPAddress ip = IPAddress.Parse(ipstr);
IPEndPoint ipe = new IPEndPoint(ip,port);
while(true)
{
try
{
Socket c= new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
string sendstr = Console.ReadLine();
byte[] sendbyte = Encoding.ASCII.GetBytes(sendstr);
c.Connect(ipe);
c.Send(sendbyte);
string recestr;
byte[] receBytes= new byte[1024];
int bytes;
bytes = c.Receive(receBytes,receBytes.Length,0);
recestr = Encoding.ASCII.GetString(receBytes,0,bytes);
Console.WriteLine("from server msg"+recestr);
c.Shutdown(SocketShutdown.Both);
c.Close();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
catch(SocketException sc)
{
Console.WriteLine("SocketeException "+sc.Message);
}
catch(Exception e)
{
Console.WriteLine("Exception "+e.Message); }
Console.WriteLine("Press Enter to Exit");
Console.ReadLine();
}
报异常信息为:一个封锁操作被对 WSACancelBlockingCall 的调用中断。
服务端代码
class Class1
{
public static bool flag=false; //函数Receive执行完毕 flag 置为 true
public static Socket temp=null; //接受的客户端连接
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
try
{
TimerCallback timerCallBack = new TimerCallback(ForeSendMsg);
int port =3001;
string ipstr="127.0.0.1";
IPAddress ip = IPAddress.Parse(ipstr);
IPEndPoint ipe = new IPEndPoint(ip,port);
Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
s.Bind(ipe);
s.Listen(50);
Console.WriteLine("begin listen ...." );
while(true)
{
flag = false;
temp=null;
temp = s.Accept();
string receStr;
byte[] receBytes = new byte[1024];
int bytes;
Console.WriteLine("start receive.........");
Timer timer = new Timer(timerCallBack,temp,3000,0); //设置定时器,3秒之后,如果Receive还没有执行完毕,认为超时,本次不再接受客户端数据,返回给客户端超时消息
bytes=temp.Receive(receBytes,0,receBytes.Length,SocketFlags.Partial);
flag=true;
Console.WriteLine("End receive............");
receStr = Encoding.GetEncoding("utf-8").GetString(receBytes,0,bytes);
Log.WriteLog("test",new StringBuilder(receStr+"\r\n"));
Console.WriteLine("receive msg="+receStr);
string sendstr = "ok!"+"dsssssssssssssss";
byte[] bs = Encoding.ASCII.GetBytes(sendstr);
temp.Send(bs,0,bs.Length,SocketFlags.None);
temp.Shutdown(SocketShutdown.Both);
temp.Close();
}
//s.Close();
}
catch(SocketException se)
{
Log.WriteLog("test",new StringBuilder(se.Message+"\r\n"));
Console.WriteLine("SocketException "+se.Message);
}
catch(Exception ex)
{
Log.WriteLog("test",new StringBuilder(ex.Message+"\r\n"));
Console.WriteLine("Exception "+ex.Message);
}
}
public static void ForeSendMsg(Object tmp)
{
Socket temp = (Socket)tmp;
if(temp!=null&&flag==false&&temp.Connected)
{
temp.Shutdown(SocketShutdown.Receive);
Console.WriteLine("Time is reach");
byte[] arr = Encoding.ASCII.GetBytes("Exception from 1");
temp.Send(arr);
temp.Shutdown(SocketShutdown.Both);
temp.Close();
}
}
}
客户端代码如下
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
// try
{
int port =3001;
string ipstr="127.0.0.1";
IPAddress ip = IPAddress.Parse(ipstr);
IPEndPoint ipe = new IPEndPoint(ip,port);
while(true)
{
try
{
Socket c= new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
string sendstr = Console.ReadLine();
byte[] sendbyte = Encoding.ASCII.GetBytes(sendstr);
c.Connect(ipe);
c.Send(sendbyte);
string recestr;
byte[] receBytes= new byte[1024];
int bytes;
bytes = c.Receive(receBytes,receBytes.Length,0);
recestr = Encoding.ASCII.GetString(receBytes,0,bytes);
Console.WriteLine("from server msg"+recestr);
c.Shutdown(SocketShutdown.Both);
c.Close();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
catch(SocketException sc)
{
Console.WriteLine("SocketeException "+sc.Message);
}
catch(Exception e)
{
Console.WriteLine("Exception "+e.Message); }
Console.WriteLine("Press Enter to Exit");
Console.ReadLine();
}
解决方案 »
- C#中当前窗体的问题!!!!!急!急!
- 时间参数中的e不懂
- 怎么把能比较方便的把C# Winform 的treeview控件的数据保存到数据库里面,不通过Insert语句怎么实现?
- 帮帮忙
- 请问:如何获取下列系统信息?
- 斑竹和高手请进,如果你回答出来,请搜索我的提问,并up一下,我把那些未结的贴子的分都给你!
- 水晶报表9时如何发布的
- 将word文档内容导成xml然后从xml导出到webform页面指定的控件中,如textbox中
- 重开贴问:用winform做个题库类软件,单机版,用到什么关键控件
- 关于unsafe,高分速求解答
- 关于字符串的筛选,求一个解决方案。正则亦可!
- 怎么向changepassword登录控件中的按钮添加背景图?急急急急急急急急急急急急急急急急急急急急急急~~~~~
估计是客户端敲回车刚好是发送键,于是发送了空字符串,导致服务器端和客户端都阻塞,
再不行使用异步吧~