首页 新闻 搜索 专区 学院

C# socket异步接收数据的问题

0
悬赏园豆:5 [已解决问题] 解决于 2014-09-19 11:57

服务器端第一次能接收到数据,客户端第二次发送数据的时候就接收不到了,客户端判断了下,连接也没中断,也没有发出异常,是我接收数据的方式不对还是什么,麻烦各位给看看;

 

  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 }
客户端代码
DoNetCoder的主页 DoNetCoder | 初学一级 | 园豆:3
提问于:2014-09-19 10:18
< >
分享
最佳答案
0

大致分析你的代码,几个疑问:

1、ManualResetEvent干吗用的?(好久不用SOCKET了,out了)

2、为什么用ManualResetEvent?是否有不合理的地方?

3、你的socket里的receive,感觉怪怪的。

4、作为服务器的listener,它应该只做一件事情:死循环直到退出,而循环内容就是接收连接请求,而你的代码有什么reset,有什么wait,感觉这个是一个问题。

5、socket建立连接后,C/S双方都是基于这个socket进行通讯,不再受listener和connect的控制才对。

收获园豆:3
519740105 | 大侠五级 |园豆:5810 | 2014-09-19 10:29

谢谢你的问题,ManualResetEvent应该是阻塞线程等待连接用的(我理解的不知道对不对,我也不知道干嘛要用他,),也看过有人说异步socket干嘛还用ManualResetEvent,说是MSDN毒害了很多人,以前没接触socket,网上也N多版本,不知道哪个才是纯正的写法,特来此请教

DoNetCoder | 园豆:3 (初学一级) | 2014-09-19 10:46

@DoNetCoder: 把这个都删除看。同时分析这个类的具体作用。

519740105 | 园豆:5810 (大侠五级) | 2014-09-19 10:47

@519740105: 之前也试过去掉,去掉之后内存全都被消耗掉了,想不重启都不行

DoNetCoder | 园豆:3 (初学一级) | 2014-09-19 11:14

@DoNetCoder: 那是你的服务监听有问题导致的。

当然,你这个叫异步socket,我没怎么弄过,也只能给你瞎出主意。

简单的socket编程,.net有更好的封装的,分别是system.net.sockets.tcpclient和system.net.sockets.tcplistener,你可以从这个开始去认识socket编程,然后再从这个高级的封装转到低级的socket编程。

同时,在执行纯socket编程的时候,先不要做什么socket异步,直接弄同步的socket,最后再考虑异步socket。

519740105 | 园豆:5810 (大侠五级) | 2014-09-19 11:40
其他回答(5)
0

你看看你第二次发的包的大小,我以前做的时候也是这样的情况,之后发现是因为包的大小有点大,被路由器拦截了,一般路由器每次允许通过的最大包大小应该是1024个字节。在发送数据的时候应该采取切包、粘包的方式来处理。

收获园豆:1
Coder²º¹5 | 园豆:15 (初学一级) | 2014-09-19 10:24

感谢你的回答,不过我的应该不是包的问题吧,应为我发的包只是随便输入的几个字符,几条加起来也就是十几二十几个字节

支持(0) 反对(0) DoNetCoder | 园豆:3 (初学一级) | 2014-09-19 10:30
0
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));
       }
客户端

这是我以前写的,不知道对你有帮助没。

收获园豆:1
小林丶2013 | 园豆:2 (初学一级) | 2014-09-19 11:19

谢谢你的代码

支持(0) 反对(0) DoNetCoder | 园豆:3 (初学一级) | 2014-09-19 11:28

@DoNetCoder: 可以用吗

支持(0) 反对(0) 小林丶2013 | 园豆:2 (初学一级) | 2014-09-19 11:29

@小林丶2013: 因为对异步有太多不了解,我想用异步实现

支持(0) 反对(0) DoNetCoder | 园豆:3 (初学一级) | 2014-09-19 11:56
0

你好,你的问题怎么解决的,我也出现了,不知道怎么解决

WEO'es | 园豆:194 (初学一级) | 2014-12-08 14:34
0

你下面的接收回调函数里,把else 中的beginrecevice放在外面,你这个写法错误就在于他没能持续监听接受信息

陌莜柒 | 园豆:202 (菜鸟二级) | 2015-07-31 10:20
0
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);
 }



高效养猪倌 | 园豆:196 (初学一级) | 2016-12-28 19:34
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册