socket通信以及C#多线程问题

愈来愈好 2016-12-15 10:37:17
现有三个线程,第一个线程是专门用来接收socket发来的数据包,第二、三两个线程是对数据包的内容进行分析,并应用。之前是没有单独开一个线程来接受字符串放在第二或者第三个线程中,但是在测试中发现只要数据量大一点,对数据包分析的时间长一点,接收数据的字符串格式就会乱。然后开了一个接收字符串的线程过后,但是整个程序被这个线程抢占了太多资源,接收字符串问题解决了,但是程序太卡了。所以请问有什么办法来避免这个问题?还是只能将字符串接收放在第二或者第三个线程中,然后对接收到的数据进行筛选吗?或者每次接收数据后返回一个数据给客户端,客户端接收后再发第二条(现在客户端发送数据是一直不停的发送的)?
 
s = new Thread(RecStr); // 创建一个接收字符串线程
s.Start();
t = new Thread(new ParameterizedThreadStart(dealPic)); // 创建一个Picturebox处理线程
t.Start(mfrm);
p = new Thread(new ParameterizedThreadStart(dealLab)); // 创建一个label处理线程
p.Start(mfrm);

public static void RecStr()
{
do
{
int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息
Console.WriteLine("Reading data,{0} bytes...", bytesRead);
//获得请求的字符串
recStr = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received:{0}", recStr);
//Thread.Sleep(1000);
} while (true);
}
...全文
520 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
基本上,如果只是教一个初学者一个基本概念、基本语法,可能会举出“两个线程”之类的例子。 但是专业一点点的软件设计,跟初学者的根本区别,就在于重构的深度。软件设计模式完全是实际的模式,不是从一开始就看上去完全无厘头的想当然地设计模式。你的设计完全是坑爹的那种,是自己想的设计?还是一些坑人的博客作者给你的?
  • 打赏
  • 举报
回复
滥用线程概念匹配到“客户端”名词儿上,然后又滥用“队列”概念去扯出来更多的死循环的什么“消费者线程”,这从根本上就是一个设计误区。 “生产者-消费者”模式被胡乱套用在这里,毫无意义。
  • 打赏
  • 举报
回复
引用 楼主 u012094400 的回复:
现有三个线程,第一个线程是专门用来接收socket发来的数据包,第二、三两个线程是对数据包的内容进行分析,并应用。
这是什么鬼逻辑啊?你是不是从多年前的那些比较坑人的 java 教程上学的通讯编程啊? socket 接收到发来的数据,windows系统的 IOCP 机制会触发事件,你的应用程序会使用 I/O 线程来回调你之前注册的处理任务,仅此而已!用不着你去纠结什么“一个线程死循环”的编程逻辑。 如果有10万客户端连接,你也不需要1个线程,更不需要100001个线程在那里死循环着(此时你的内存得多大?CPU得多卡?)
浴浴兮 2016-12-15
  • 打赏
  • 举报
回复
最好是交互 就是你说的 每次接收数据后返回一个数据给客户端 如果不行就约定 在传过来的信息里面加个头 把长度传进去 你根据长度读 do { int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 recStr = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", recStr); //Thread.Sleep(1000); 不断循环肯定占CPU Thread.Sleep(1); } while (true);
愈来愈好 2016-12-15
  • 打赏
  • 举报
回复
引用 8 楼 xian_wwq 的回复:
[quote=引用 6 楼 u012094400 的回复:] [quote=引用 1 楼 a6733351018 的回复:] 最好是交互 就是你说的 每次接收数据后返回一个数据给客户端 如果不行就约定 在传过来的信息里面加个头 把长度传进去 你根据长度读 do { int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 recStr = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", recStr); //Thread.Sleep(1000); 不断循环肯定占CPU Thread.Sleep(1); } while (true);
现在穿过来的数据包有头尾标识符,但是会出现我这一次接收的字符串可能有头没有尾,这个时候是不是应该把这次接收的字符串保存起来,然后继续接收下一端数据包,这样子处理好麻烦啊。。。发送端是一条一条发送的,有没有什么办法能够一条一条的接收啊?只能通过客户端与服务端交互才能实现吗?[/quote] tcp没有一条一条的概念,因为tcp是基于流的 所以发送的是一条一条,但是接收到的数据可能还是一条一条,也可能是混在一起。 这个需要在数据解包时通过约定的头尾进行处理, 也就是所谓的“粘包”处理 [/quote] 谢谢,好的,那这样子接收需要对字符串进行分析,分析需要的时间会不会影响同步问题啊?
愈来愈好 2016-12-15
  • 打赏
  • 举报
回复
引用 7 楼 xian_wwq 的回复:
[quote=引用 楼主 u012094400 的回复:] 现有三个线程,第一个线程是专门用来接收socket发来的数据包,第二、三两个线程是对数据包的内容进行分析,并应用。之前是没有单独开一个线程来接受字符串放在第二或者第三个线程中,但是在测试中发现只要数据量大一点,对数据包分析的时间长一点,接收数据的字符串格式就会乱。然后开了一个接收字符串的线程过后,但是整个程序被这个线程抢占了太多资源,接收字符串问题解决了,但是程序太卡了。所以请问有什么办法来避免这个问题?还是只能将字符串接收放在第二或者第三个线程中,然后对接收到的数据进行筛选吗?或者每次接收数据后返回一个数据给客户端,客户端接收后再发第二条(现在客户端发送数据是一直不停的发送的)?
 
                s = new Thread(RecStr);			// 创建一个接收字符串线程
                s.Start();
                t = new Thread(new ParameterizedThreadStart(dealPic));			// 创建一个Picturebox处理线程
                t.Start(mfrm);
                p = new Thread(new ParameterizedThreadStart(dealLab));			// 创建一个label处理线程
                p.Start(mfrm);

  public static void RecStr()
        {
            do
            {             
                int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息
                Console.WriteLine("Reading data,{0} bytes...", bytesRead);
                //获得请求的字符串
                recStr = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                Console.WriteLine("Received:{0}", recStr);
                //Thread.Sleep(1000);
            } while (true);
         }
1.数据接收线程的功能一定要够简洁,接收byte[]后,把数据放入线程安全的容器中, 接收线程的工作就可以结束了。 后续的解析线程从改容器中读取数据进行解析处理。 2. 数据解析是高频,短时间就可以完成的操作。 不要使用单个线程, 推荐使用线程池[/quote] 因为服务器端的界面数据需要从客户端发送过来因此数据需要不停的接收,随着程序的开始而开始结束而结束,在这种情况下,数据是接收一部分就得处理一部分,这样子不停从容器中取东西存东西,影响大吗?
xian_wwq 2016-12-15
  • 打赏
  • 举报
回复
引用 6 楼 u012094400 的回复:
[quote=引用 1 楼 a6733351018 的回复:] 最好是交互 就是你说的 每次接收数据后返回一个数据给客户端 如果不行就约定 在传过来的信息里面加个头 把长度传进去 你根据长度读 do { int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 recStr = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", recStr); //Thread.Sleep(1000); 不断循环肯定占CPU Thread.Sleep(1); } while (true);
现在穿过来的数据包有头尾标识符,但是会出现我这一次接收的字符串可能有头没有尾,这个时候是不是应该把这次接收的字符串保存起来,然后继续接收下一端数据包,这样子处理好麻烦啊。。。发送端是一条一条发送的,有没有什么办法能够一条一条的接收啊?只能通过客户端与服务端交互才能实现吗?[/quote] tcp没有一条一条的概念,因为tcp是基于流的 所以发送的是一条一条,但是接收到的数据可能还是一条一条,也可能是混在一起。 这个需要在数据解包时通过约定的头尾进行处理, 也就是所谓的“粘包”处理
xian_wwq 2016-12-15
  • 打赏
  • 举报
回复
引用 楼主 u012094400 的回复:
现有三个线程,第一个线程是专门用来接收socket发来的数据包,第二、三两个线程是对数据包的内容进行分析,并应用。之前是没有单独开一个线程来接受字符串放在第二或者第三个线程中,但是在测试中发现只要数据量大一点,对数据包分析的时间长一点,接收数据的字符串格式就会乱。然后开了一个接收字符串的线程过后,但是整个程序被这个线程抢占了太多资源,接收字符串问题解决了,但是程序太卡了。所以请问有什么办法来避免这个问题?还是只能将字符串接收放在第二或者第三个线程中,然后对接收到的数据进行筛选吗?或者每次接收数据后返回一个数据给客户端,客户端接收后再发第二条(现在客户端发送数据是一直不停的发送的)?
 
                s = new Thread(RecStr);			// 创建一个接收字符串线程
                s.Start();
                t = new Thread(new ParameterizedThreadStart(dealPic));			// 创建一个Picturebox处理线程
                t.Start(mfrm);
                p = new Thread(new ParameterizedThreadStart(dealLab));			// 创建一个label处理线程
                p.Start(mfrm);

  public static void RecStr()
        {
            do
            {             
                int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息
                Console.WriteLine("Reading data,{0} bytes...", bytesRead);
                //获得请求的字符串
                recStr = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                Console.WriteLine("Received:{0}", recStr);
                //Thread.Sleep(1000);
            } while (true);
         }
1.数据接收线程的功能一定要够简洁,接收byte[]后,把数据放入线程安全的容器中, 接收线程的工作就可以结束了。 后续的解析线程从改容器中读取数据进行解析处理。 2. 数据解析是高频,短时间就可以完成的操作。 不要使用单个线程, 推荐使用线程池
愈来愈好 2016-12-15
  • 打赏
  • 举报
回复
引用 1 楼 a6733351018 的回复:
最好是交互 就是你说的 每次接收数据后返回一个数据给客户端 如果不行就约定 在传过来的信息里面加个头 把长度传进去 你根据长度读 do { int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 recStr = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", recStr); //Thread.Sleep(1000); 不断循环肯定占CPU Thread.Sleep(1); } while (true);
现在穿过来的数据包有头尾标识符,但是会出现我这一次接收的字符串可能有头没有尾,这个时候是不是应该把这次接收的字符串保存起来,然后继续接收下一端数据包,这样子处理好麻烦啊。。。发送端是一条一条发送的,有没有什么办法能够一条一条的接收啊?只能通过客户端与服务端交互才能实现吗?
愈来愈好 2016-12-15
  • 打赏
  • 举报
回复
引用 4 楼 sp1234 的回复:
基本上,如果只是教一个初学者一个基本概念、基本语法,可能会举出“两个线程”之类的例子。 但是专业一点点的软件设计,跟初学者的根本区别,就在于重构的深度。软件设计模式完全是实际的模式,不是从一开始就看上去完全无厘头的想当然地设计模式。你的设计完全是坑爹的那种,是自己想的设计?还是一些坑人的博客作者给你的?
看的博客,自己也是个初学者,对于这块儿了解不深,有没有推荐的博客啊?我去研究研究

110,534

社区成员

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

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

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