服务器端第一次能接收到数据,客户端第二次发送数据的时候就接收不到了,客户端判断了下,连接也没中断,也没有发出异常,是我接收数据的方式不对还是什么,麻烦各位给看看;
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net; 6 using System.Net.Sockets; 7 using System.Threading; 8 using System.Text.RegularExpressions; 9 10 namespace ServerSample 11 { 12 class Program 13 { 14 public static ManualResetEvent allDone = new ManualResetEvent(false); 15 public const string pattern = @"(?<=^\[len=)(\d+)(?=\])";//数据包正则,获取数据包长度 16 17 static void Main(string[] args) 18 { 19 Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 20 try 21 { 22 listener.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 59999)); 23 listener.Listen(10); 24 Console.WriteLine("开启监听..."); 25 while (true) 26 { 27 allDone.Reset(); 28 listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 29 allDone.WaitOne(); 30 } 31 } 32 catch (Exception e) 33 { 34 Console.WriteLine(e); 35 } 36 Console.ReadKey(); 37 38 } 39 static void AcceptCallback(IAsyncResult ar) 40 { 41 allDone.Set(); 42 Socket listener = ar.AsyncState as Socket; 43 StateObject state = new StateObject(); 44 Socket socket = listener.EndAccept(ar); 45 Console.WriteLine("有新的连接:{0}", socket.RemoteEndPoint); 46 state.socket = socket; 47 socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), state); 48 } 49 50 static void ReceiveCallback(IAsyncResult ar) 51 { 52 string context = string.Empty; 53 StateObject state = ar.AsyncState as StateObject; 54 Socket socket = state.socket; 55 Int32 recCount = socket.EndReceive(ar); 56 if (recCount > 0) 57 { 58 state.sb.Append(Encoding.Unicode.GetString(state.buffer, 0, recCount)); 59 context = state.sb.ToString(); 60 if (Regex.IsMatch(context, pattern)) 61 { 62 Match m = Regex.Match(context, pattern); 63 Int32 len = Convert.ToInt32(m.Groups[0].Value); 64 Int32 startIndex = context.IndexOf(']') + 1; 65 string output = context.Substring(startIndex); 66 Console.WriteLine("接收到了:{0}", output); 67 //socket.Close(); 68 } 69 else 70 { 71 socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, ReceiveCallback, state); 72 } 73 } 74 75 76 } 77 78 79 } 80 public class StateObject 81 { 82 83 // Client socket. 84 85 public Socket socket = null; 86 87 // Size of receive buffer. 88 89 public const int BufferSize = 128; 90 91 // Receive buffer. 92 93 public byte[] buffer = new byte[BufferSize]; 94 95 // Received data string. 96 97 public StringBuilder sb = new StringBuilder(); 98 99 } 100 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Net; 5 using System.Net.Sockets; 6 using System.Text; 7 using System.Threading; 8 9 namespace ClientSample 10 { 11 class Program 12 { 13 private static ManualResetEvent connectDone = new ManualResetEvent(false); 14 15 private static ManualResetEvent sendDone = new ManualResetEvent(false); 16 17 static void Main(string[] args) 18 { 19 Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 20 client.BeginConnect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 59999), new AsyncCallback(ConncetCallback), client); 21 connectDone.WaitOne(); 22 23 while (true) 24 { 25 26 string input = CombineString(Console.ReadLine()); 27 Console.WriteLine(input); 28 byte[] sendData = Encoding.Unicode.GetBytes(input); 29 if (client.Connected) 30 { 31 client.BeginSend(sendData, 0, sendData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client); 32 sendDone.WaitOne(); 33 } 34 } 35 36 } 37 38 static void ConncetCallback(IAsyncResult ar) 39 { 40 Socket client = ar.AsyncState as Socket; 41 42 client.EndConnect(ar); 43 Console.WriteLine("与服务器建立连接..."); 44 connectDone.Set(); 45 } 46 47 static void SendCallback(IAsyncResult ar) 48 { 49 Socket client = ar.AsyncState as Socket; 50 client.EndSend(ar); 51 sendDone.Set(); 52 } 53 54 private static string CombineString(string input) 55 { 56 return string.Format("[len={0}]{1}", input.Length, input); 57 } 58 } 59 }
大致分析你的代码,几个疑问:
1、ManualResetEvent干吗用的?(好久不用SOCKET了,out了)
2、为什么用ManualResetEvent?是否有不合理的地方?
3、你的socket里的receive,感觉怪怪的。
4、作为服务器的listener,它应该只做一件事情:死循环直到退出,而循环内容就是接收连接请求,而你的代码有什么reset,有什么wait,感觉这个是一个问题。
5、socket建立连接后,C/S双方都是基于这个socket进行通讯,不再受listener和connect的控制才对。
谢谢你的问题,ManualResetEvent应该是阻塞线程等待连接用的(我理解的不知道对不对,我也不知道干嘛要用他,),也看过有人说异步socket干嘛还用ManualResetEvent,说是MSDN毒害了很多人,以前没接触socket,网上也N多版本,不知道哪个才是纯正的写法,特来此请教
@DoNetCoder: 把这个都删除看。同时分析这个类的具体作用。
@519740105: 之前也试过去掉,去掉之后内存全都被消耗掉了,想不重启都不行
@DoNetCoder: 那是你的服务监听有问题导致的。
当然,你这个叫异步socket,我没怎么弄过,也只能给你瞎出主意。
简单的socket编程,.net有更好的封装的,分别是system.net.sockets.tcpclient和system.net.sockets.tcplistener,你可以从这个开始去认识socket编程,然后再从这个高级的封装转到低级的socket编程。
同时,在执行纯socket编程的时候,先不要做什么socket异步,直接弄同步的socket,最后再考虑异步socket。
你看看你第二次发的包的大小,我以前做的时候也是这样的情况,之后发现是因为包的大小有点大,被路由器拦截了,一般路由器每次允许通过的最大包大小应该是1024个字节。在发送数据的时候应该采取切包、粘包的方式来处理。
感谢你的回答,不过我的应该不是包的问题吧,应为我发的包只是随便输入的几个字符,几条加起来也就是十几二十几个字节
static Socket clientSocket = null; static Thread thread = null; static Socket accSck = null; /// <summary> /// 开启监听 /// </summary> public static void OpenListener(Form1 form) { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ip = IPAddress.Parse("127.0.0.1"); IPEndPoint endPoint = new IPEndPoint(ip, 8888); clientSocket.Bind(endPoint); clientSocket.Listen(10); thread = new Thread(JtSocket); thread.IsBackground = true; thread.Start(); } private static void JtSocket() { while (true) { accSck = clientSocket.Accept(); byte[] data = new byte[1024]; accSck.Receive(data); string rt = System.Text.UTF8Encoding.UTF8.GetString(data); } } public static void SendMsg(string msg) { accSck.Send(Encoding.UTF8.GetBytes(msg)); }
private static Socket clientSocket = null; private static Thread thread = null; /// <summary> /// 连接服务器端 /// </summary> public static void Connect() { clientSocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); IPAddress ip = IPAddress.Parse("127.0.0.1"); IPEndPoint endPoint=new IPEndPoint(ip,8888); clientSocket.Connect(endPoint); thread = new Thread(ReceMsg); thread.IsBackground = true; thread.Start(); } /// <summary> /// 接收服务器端数据 /// </summary> private static void ReceMsg() { while (true) { byte[] buffer=new byte[1024]; clientSocket.Receive(buffer); } } public static void SendMsg(string msg) { clientSocket.Send(Encoding.UTF8.GetBytes(msg)); }
这是我以前写的,不知道对你有帮助没。
谢谢你的代码
@DoNetCoder: 可以用吗
@小林丶2013: 因为对异步有太多不了解,我想用异步实现
你好,你的问题怎么解决的,我也出现了,不知道怎么解决
你下面的接收回调函数里,把else 中的beginrecevice放在外面,你这个写法错误就在于他没能持续监听接受信息
if (recCount > 0)
{
state.sb.Append(Encoding.Unicode.GetString(state.buffer, 0, recCount));
context = state.sb.ToString();
if (Regex.IsMatch(context, pattern))
{
Match m = Regex.Match(context, pattern);
Int32 len = Convert.ToInt32(m.Groups[0].Value);
Int32 startIndex = context.IndexOf(']') + 1;
string output = context.Substring(startIndex);
Console.WriteLine("接收到了:{0}", output);
//socket.Close();
}
else
{
socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, ReceiveCallback, state);
}
}
改成下面就对了
if (recCount > 0)
{
state.sb.Append(Encoding.Unicode.GetString(state.buffer, 0, recCount));
context = state.sb.ToString();
if (Regex.IsMatch(context, pattern))
{
Match m = Regex.Match(context, pattern);
Int32 len = Convert.ToInt32(m.Groups[0].Value);
Int32 startIndex = context.IndexOf(']') + 1;
string output = context.Substring(startIndex);
Console.WriteLine("接收到了:{0}", output);
//socket.Close();
}
}
else
{
socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, ReceiveCallback, state);
}