winsock 多客户端动态连接多服务器,及发送接收大数据问题

时间:2022-09-12 20:16:35
超难winsock复杂通信问题,向各专家提问,因为分数不够,所以只能这样发,望大家共同讨论!
因需要,设计如下WINSOCK需求:


   软件端:(100个以上,既是客户端,又是服务端)
  1)、各软件端需要winscok 服务端及客户端,都要求有统一固定端口号,如服务端端口(2215),客户端端口(2216);
  2)、服务端一直处于监听任何客户端过来的连接请求,并响应请求,调用相应过程处理,完成后返回处理结果,并释放
       相应的连接。
  3)、客户端在在有发送请求的时候动态连接相应的服务端,并发送数据,等待服务端的响应,完成后即关闭连接。
       在客户端发送数据的时候,其它发送请求则排队等待完成后再发送。

   问题:
  4)、当数据大于8K时,在接收端接收数据不完整;
  5)、当客户端设定固定端口后,第一次连接关闭后,再次连接不了服务端;
  6)、如何让客户端排队发送数据。

17 个解决方案

#1


补充:如何判断客户端与服务端连接失败,是否可以设置连接超时限制?

#2


你的逻辑得设计好

通讯协议也要做得比较健壮,无漏洞,方便扩展与维护...

这个不光是代码的问题了(相信你能问到这份上,代码问题应该已经不是问题了)

至于检测是否活动,一般的做法是发送心跳包,在服务器端上收到后,定期更新一个"最后活动时间",然后与当前时间比较,超过某一时间就表示这个客户端挂了....

#3


有个问题。麻烦楼主说一下。。。
请问楼主要做什么?方便说就说一下。。。
“各软件端需要winscok 服务端及客户端”
“服务端一直处于监听任何客户端过来的连接请求,并响应请求,调用相应过程处理,完成后返回处理结果,并释放 
      相应的连接。” 
“ 当客户端设定固定端口后,第一次连接关闭后,再次连接不了服务端;”
这几个问题貌似你就不应该用TCP!!!
该用UDP。
所以,要是方便的话就说说具体实现什么

#4


感谢各位的热忱帮助!
1、通讯协议用的都是TCP,服务器端监听2216端口,客户端用2215和服务端连接。当客户端在第一次连接服务端断开后,第二次在连接服务端就连不上。不知道是什么问题。服务端是用winsock数组监听各客户端来的连接。
2、如果用心跳包来测试,也有一定的问题。客户端是在需要的时候才和服务端连接。服务端用心跳包来检测和客户端的连接是否通畅,那数据量太大,因为客户端可能是100 也可能是 500,甚至可能达到1000。
3、另外,WINSOCK在接收大于8K的数据时,出现数据不完整的情况。这儿问题不知道有什么好的方法可以解决。我在网上看了些,但觉得那些方法不是很完善
4、另外程序不知道如何才能做成系统服务,可以随系统启动时自动启动



关于3楼朋友的问题,具体如下:
1、各软件端既是客户端也是服务端,可以连接别的服务器,别的服务器也可以连接它
2、本软件是一公司的应用软件,目前有200多台服务器,在这些服务器之间可以互相交换数据。

#5


可能要用到广播和令牌。每个计算机上要维护一个在线计算机列表。
程序启动时发送广播,告知大家自己上线的信息;
收到这个消息的计算机就将该计算机的信息加到自己的在线列表中,同时将自己的信息反馈给新上线计算机,以便在新上线计算机上添加在线列表;
同样程序退出时也要发送广播,以便其它计算机从在线列表中删除。

每个计算机有一个允许访问的令牌,根据在线列表,循环将令牌发送到某个计算机上;
收到的计算机不需要访问该服务器、或者正在访问其它服务器,那么马上将令牌返回服务器;否则就可以访问服务器,完成后返回令牌;
服务端如果发送令牌后没响应、或者一定时间内没收到数据,将该客户段视为故障,直接将令牌传递给下个客户端。

由于令牌和广播的数据量比较小,新开一对固定的发送/接收端口应该够用了。

#6


服务器都是公网IP。不在局域网内,至于访问授权专门有验证的。

#7


那么就从验证服务器上取得在线列表。
关键是用令牌解决资源独占(允许访问某个服务端)的问题,如果可能的话,建立一个专门的服务端进行令牌控制。

就像 BT 软件一样,数据传递是 P2P 的,可是种子还是要由专门的服务器来进行管理的,可以借鉴这种思路。

#8


谢谢楼上朋友的关注。各服务器的IP列表问题我已经解决。现在是WINSOCK连接及数据发送、接收控制方面的问题。

#9


如果你控制好客户端/服务端每次都是一一对应进行通讯,那么应该不会发生关闭后不能连接的问题。

数据发送/接收要有反馈机制:
客户端将数据划分成比若干个较小的包分别发送,每发送一个包就暂停;
服务端收完一个包后反馈给客户端,然后客户端再发送下一个包。

#10


对于各问题的解答:

  1)、各软件端需要winscok 服务端及客户端,都要求有统一固定端口号,如服务端端口(2215),客户端端口(2216); 

  2)、服务端一直处于监听任何客户端过来的连接请求,并响应请求,调用相应过程处理,完成后返回处理结果,并释放 
      相应的连接。 
  3)、客户端在在有发送请求的时候动态连接相应的服务端,并发送数据,等待服务端的响应,完成后即关闭连接。 
      在客户端发送数据的时候,其它发送请求则排队等待完成后再发送。 

  问题: 
  4)、当数据大于8K时,在接收端接收数据不完整; 
  5)、当客户端设定固定端口后,第一次连接关闭后,再次连接不了服务端; 
  6)、如何让客户端排队发送数据。

#11


上面的不小心按错了。

对于各问题的解答: 

  问题: 
  4)、当数据大于8K时,在接收端接收数据不完整; 
       答:我以前也用VB做过这个这种传输大文件的,是有这个问题,我是在发送端把要发送的数据分成每8K一段,一次发送一段,循环发送,直至完成,效果不错,发送几百兆的文件也没有问题,你可以试试。

  5)、当客户端设定固定端口后,第一次连接关闭后,再次连接不了服务端; 
       答:你应该是用了winsock控件数组来监听,所有的数组都做监听吧?那样的话你每次完成数据需要监听的时候需要关闭连接,然后再启动监听。其实这里有一个比较好的做法,就是另外用一个不需进行连接和接收数据的winsock进行监听,产生ConnectRequest事件后,用其它空闲的winsock来Accept接受连接,这样子监听就会一直存在,也就可以一直监听客户端的请求

  6)、如何让客户端排队发送数据。
       答:如果你的是控件数组应该不需要排队发数据的,如果你客户端连接很多,你服务器端只有一个winsock控件,那么你想让100个客户端都要发送数据的时候等一个发完再发下一个,那么你就要考虑各个客户端之间的信息传递,你可以用文件、共享内存、消息等,在任何一个客户端要发送数据前发送开始发送数据的标志给所有客户端,在SendDataComplete事件再发结束发送数据的标志给所有客户端就可以了。

#12


4)、当数据大于8K时,在接收端接收数据不完整;
发送方发多大都没关系,问题在接收方,一次只能收8K数据,发送方应该在发送数据时做好相应的协议,如:4个字节存放当前发送数据的总长度。
接收方收到第一个包后首先读取长度,和当前接收到的包长度比较,要是小了就暂存好,再收下一个包,拼接到前一个包后面,直到数据全部接收完毕。
5)、当客户端设定固定端口后,第一次连接关闭后,再次连接不了服务端;
我的做法是这样的:服务器用一个WINSOCK数组如0-300,0号用于侦听,0号收到请求后,查找1-300内空闲的对客户端请求进行连接,用完后关闭
6)、如何让客户端排队发送数据。
客户端与服务器端建立连接后,先发送一个特定指令如请求发送数据,服务器端收到后回复可否发送,客户端接到回复再根据结果发送数据或延后发送

#13


在客户端连接关闭之后,服务器关闭连接,再打开连接,重新进行侦听

#14


如果有多个连接客户端连接,则使用专门的winsocket进行侦听,一旦有客户端的连接,则用新的winsocket进行连接,客户端断开后,关闭连接。

#15


楼主应用的节点比较多,容易引发拥堵,用令牌比较好控制。

#16


弄了这些天,还是没弄好,望多多赐教,如能提供代码学习下,那最好了,谢谢各位朋友热诚的回复!

#17


引用 15 楼 Tiger_Zhao 的回复:
楼主应用的节点比较多,容易引发拥堵,用令牌比较好控制。

怎样有令牌,可否写点代码参考下?

#1


补充:如何判断客户端与服务端连接失败,是否可以设置连接超时限制?

#2


你的逻辑得设计好

通讯协议也要做得比较健壮,无漏洞,方便扩展与维护...

这个不光是代码的问题了(相信你能问到这份上,代码问题应该已经不是问题了)

至于检测是否活动,一般的做法是发送心跳包,在服务器端上收到后,定期更新一个"最后活动时间",然后与当前时间比较,超过某一时间就表示这个客户端挂了....

#3


有个问题。麻烦楼主说一下。。。
请问楼主要做什么?方便说就说一下。。。
“各软件端需要winscok 服务端及客户端”
“服务端一直处于监听任何客户端过来的连接请求,并响应请求,调用相应过程处理,完成后返回处理结果,并释放 
      相应的连接。” 
“ 当客户端设定固定端口后,第一次连接关闭后,再次连接不了服务端;”
这几个问题貌似你就不应该用TCP!!!
该用UDP。
所以,要是方便的话就说说具体实现什么

#4


感谢各位的热忱帮助!
1、通讯协议用的都是TCP,服务器端监听2216端口,客户端用2215和服务端连接。当客户端在第一次连接服务端断开后,第二次在连接服务端就连不上。不知道是什么问题。服务端是用winsock数组监听各客户端来的连接。
2、如果用心跳包来测试,也有一定的问题。客户端是在需要的时候才和服务端连接。服务端用心跳包来检测和客户端的连接是否通畅,那数据量太大,因为客户端可能是100 也可能是 500,甚至可能达到1000。
3、另外,WINSOCK在接收大于8K的数据时,出现数据不完整的情况。这儿问题不知道有什么好的方法可以解决。我在网上看了些,但觉得那些方法不是很完善
4、另外程序不知道如何才能做成系统服务,可以随系统启动时自动启动



关于3楼朋友的问题,具体如下:
1、各软件端既是客户端也是服务端,可以连接别的服务器,别的服务器也可以连接它
2、本软件是一公司的应用软件,目前有200多台服务器,在这些服务器之间可以互相交换数据。

#5


可能要用到广播和令牌。每个计算机上要维护一个在线计算机列表。
程序启动时发送广播,告知大家自己上线的信息;
收到这个消息的计算机就将该计算机的信息加到自己的在线列表中,同时将自己的信息反馈给新上线计算机,以便在新上线计算机上添加在线列表;
同样程序退出时也要发送广播,以便其它计算机从在线列表中删除。

每个计算机有一个允许访问的令牌,根据在线列表,循环将令牌发送到某个计算机上;
收到的计算机不需要访问该服务器、或者正在访问其它服务器,那么马上将令牌返回服务器;否则就可以访问服务器,完成后返回令牌;
服务端如果发送令牌后没响应、或者一定时间内没收到数据,将该客户段视为故障,直接将令牌传递给下个客户端。

由于令牌和广播的数据量比较小,新开一对固定的发送/接收端口应该够用了。

#6


服务器都是公网IP。不在局域网内,至于访问授权专门有验证的。

#7


那么就从验证服务器上取得在线列表。
关键是用令牌解决资源独占(允许访问某个服务端)的问题,如果可能的话,建立一个专门的服务端进行令牌控制。

就像 BT 软件一样,数据传递是 P2P 的,可是种子还是要由专门的服务器来进行管理的,可以借鉴这种思路。

#8


谢谢楼上朋友的关注。各服务器的IP列表问题我已经解决。现在是WINSOCK连接及数据发送、接收控制方面的问题。

#9


如果你控制好客户端/服务端每次都是一一对应进行通讯,那么应该不会发生关闭后不能连接的问题。

数据发送/接收要有反馈机制:
客户端将数据划分成比若干个较小的包分别发送,每发送一个包就暂停;
服务端收完一个包后反馈给客户端,然后客户端再发送下一个包。

#10


对于各问题的解答:

  1)、各软件端需要winscok 服务端及客户端,都要求有统一固定端口号,如服务端端口(2215),客户端端口(2216); 

  2)、服务端一直处于监听任何客户端过来的连接请求,并响应请求,调用相应过程处理,完成后返回处理结果,并释放 
      相应的连接。 
  3)、客户端在在有发送请求的时候动态连接相应的服务端,并发送数据,等待服务端的响应,完成后即关闭连接。 
      在客户端发送数据的时候,其它发送请求则排队等待完成后再发送。 

  问题: 
  4)、当数据大于8K时,在接收端接收数据不完整; 
  5)、当客户端设定固定端口后,第一次连接关闭后,再次连接不了服务端; 
  6)、如何让客户端排队发送数据。

#11


上面的不小心按错了。

对于各问题的解答: 

  问题: 
  4)、当数据大于8K时,在接收端接收数据不完整; 
       答:我以前也用VB做过这个这种传输大文件的,是有这个问题,我是在发送端把要发送的数据分成每8K一段,一次发送一段,循环发送,直至完成,效果不错,发送几百兆的文件也没有问题,你可以试试。

  5)、当客户端设定固定端口后,第一次连接关闭后,再次连接不了服务端; 
       答:你应该是用了winsock控件数组来监听,所有的数组都做监听吧?那样的话你每次完成数据需要监听的时候需要关闭连接,然后再启动监听。其实这里有一个比较好的做法,就是另外用一个不需进行连接和接收数据的winsock进行监听,产生ConnectRequest事件后,用其它空闲的winsock来Accept接受连接,这样子监听就会一直存在,也就可以一直监听客户端的请求

  6)、如何让客户端排队发送数据。
       答:如果你的是控件数组应该不需要排队发数据的,如果你客户端连接很多,你服务器端只有一个winsock控件,那么你想让100个客户端都要发送数据的时候等一个发完再发下一个,那么你就要考虑各个客户端之间的信息传递,你可以用文件、共享内存、消息等,在任何一个客户端要发送数据前发送开始发送数据的标志给所有客户端,在SendDataComplete事件再发结束发送数据的标志给所有客户端就可以了。

#12


4)、当数据大于8K时,在接收端接收数据不完整;
发送方发多大都没关系,问题在接收方,一次只能收8K数据,发送方应该在发送数据时做好相应的协议,如:4个字节存放当前发送数据的总长度。
接收方收到第一个包后首先读取长度,和当前接收到的包长度比较,要是小了就暂存好,再收下一个包,拼接到前一个包后面,直到数据全部接收完毕。
5)、当客户端设定固定端口后,第一次连接关闭后,再次连接不了服务端;
我的做法是这样的:服务器用一个WINSOCK数组如0-300,0号用于侦听,0号收到请求后,查找1-300内空闲的对客户端请求进行连接,用完后关闭
6)、如何让客户端排队发送数据。
客户端与服务器端建立连接后,先发送一个特定指令如请求发送数据,服务器端收到后回复可否发送,客户端接到回复再根据结果发送数据或延后发送

#13


在客户端连接关闭之后,服务器关闭连接,再打开连接,重新进行侦听

#14


如果有多个连接客户端连接,则使用专门的winsocket进行侦听,一旦有客户端的连接,则用新的winsocket进行连接,客户端断开后,关闭连接。

#15


楼主应用的节点比较多,容易引发拥堵,用令牌比较好控制。

#16


弄了这些天,还是没弄好,望多多赐教,如能提供代码学习下,那最好了,谢谢各位朋友热诚的回复!

#17


引用 15 楼 Tiger_Zhao 的回复:
楼主应用的节点比较多,容易引发拥堵,用令牌比较好控制。

怎样有令牌,可否写点代码参考下?