完成端口 高手讨论区:完成端口服务器 如何实现客户端之间的信息转发???????

时间:2022-05-24 18:18:30


     完成端口有四个线程A、B、C、D在运行,假如第一个客户端 ONE 发送给游戏服务器的数据 DATA 被 A 线程处理,  游戏服务器的A线程处理之后要把数据发送给第二个客户端 TWO 和第三个客户端 THREE ,A线程如何知道第二个客户端 TWO 和第三个客户端 THREE 的套接子?   所有客户端的套接子信息都保存在什么地方? 即使知道套接子保存在一个链表中, 那么又如何知道第二个客户端 TWO 和第三个客户端 THREE 的套接子是链表中的哪个接点呢?
     请各位高手发表自己的看法,最好能帖出实现的源代码,谢谢!!!
     可在加分!!!

16 个解决方案

#1


当然用映射啦,自己定义一套通信协议,协议中可以标识用户的ID
例如DATA包里面包括发送者ID和接受者ID列表
其他的发挥自己的想象力去想啦

#2


使用完成端口才四个线程!还是换成别的吧。

#3


完成端口的优点之一是能够发挥多处理器的优势,如果能够每个处理器刚好一个线程正在运行,那就最好不过了。所以,四个,或者十个线程并不能代表什么。1000个线程也不代表着就好。

#4


我这里要问的问题不是几个线程的问题,我只是举个例子假如有4个线程。多少个线程与我的问题没有任何关系。我的问题是如何实现信息的转发???

#5


网络游戏在用户登陆的时候就记录下了相关的IP,端口等信息了,比如可以保存在一个数据库里面(我是说可能)这样,任何作为通讯的线程就访问这个数据库,找到相关信息不就行了?!似乎没有什么难以理解的吧?
不过我没有做过网游,也不知道是不是真的这样,但应该没有什么高深的理论。

#6


是tcp的连接呀,你要保存这个ip,和port有什么用呢?呵呵
还是保存连接的哪个socket。

#7


struct
{
  socket s;
  Client c;
。。。
}SOCKOBJ;

从SOCKOBJ的容器中找出相应的客户端,实现转发

#8


HANDLE CreateIoCompletionPort (
  HANDLE FileHandle,              // handle to file
  HANDLE ExistingCompletionPort,  // handle to I/O completion port
  ULONG_PTR CompletionKey,        // completion key
  DWORD NumberOfConcurrentThreads // number of threads to execute concurrently
);
第一个参数是Accept出来的socket句柄
第二个参数是完成端口句柄
第三个参数可以放任意的自定义指针,例如可以放一结构体指针
结构体可以这样定义:
typedef struct _CompleteKey
{
SOCKET sSocket;// socket句柄
int nUserId;// 用户id
......
}CompleteKey;
这样就可以识别了
看看书吧<<windows网络编程技术>>第8章,很简单.

#9


nightlocus(英雄本色) ( ) 信誉:100 

是tcp的连接呀,你要保存这个ip,和port有什么用呢?呵呵
还是保存连接的哪个socket。
------------------------------------------------------

支持该方法!
我现在也正在写一个消息转发程序
这个问题也想了很久
后来我也是用一个队列将客户端的socket保存起来,当然与用户ID构成了一个类
也就是说用一类或结构保存客户标识和连接的socket。

也不知还有其他什么好方法没有

楼下的继续...

#10


同意飞的做法,这应该是正确的解决办法

#11


to Fly1980(飞) :
  我想请问一下,我定义了第三个参数的结构体变量,这个变量能让多个连接共用吗?

#12


在服务器上,使用accept接受客户端的一个连接后,此函数的返回值就是一个socket值,这个值就是服务器与客户端通信的信道,你想要向哪个客户端发数据,只要在send时把SOCKET值赋成相对应的客户端就行了。这里有个问题,即在网络层上,没办法区分是哪一个客户端,你必须使用自己的协议由客户端向服务器端发送一个包,这个包用于作为客户端的标识,比如在连接之后,发一个自己的用户名给服务器,这样服务器就可以把这个端口和这个用户名对应起来,而你此后想对哪一个客户端发消息,就根据记录的用户名列表查他所对应的端口就行了。

#13


to 亚飞:
好久不见,甚是想念。

使用数据库记录这样的信息是不可取的,因为在服务器的诸多控制中,会多次使用到这个端口信息,一般是建立一个HASH表来存取,速度快。

#14


to intraweb(★人贱人爱★):
第三个参数本来就是为了识别客户,为什么还要公用??
正确的方法是有一个容器存放第三个参数集合(也就是客户集合),例如数组.
每accept出来一个客户时就new一个结构体,并加入到容器中.
当与客户对应的socket上有信号(读完成,写完成...)时,就能够取到对应的结构体指针.
这样就可以做任何事情了..

#15


说来说去就是要自己建立一个 Session Pool ,内存中的, 就象 ASP.Net 和 JSP 实现的那样, 不过它们更复杂,而楼主这个比较简单。

关于 完成端口 的完美运用,建议大家看看 CodeProject 上的那个 JetByteTools,堪称经典!

BTW:
HANDLE CreateIoCompletionPort (
  HANDLE FileHandle,              // handle to file
  HANDLE ExistingCompletionPort,  // handle to I/O completion port
  ULONG_PTR CompletionKey,        // completion key
  DWORD NumberOfConcurrentThreads // number of threads to execute concurrently
);
表面上看第一个参数是 handle to file,但不要误解,完成端口可以控制任何资源的,如:硬盘文件、网络Socket端口,JetByteTools 简直是把它运用得炉火纯青,是居家旅行之必备良药……

#16


请问楼上的哪里有卖丫?

#1


当然用映射啦,自己定义一套通信协议,协议中可以标识用户的ID
例如DATA包里面包括发送者ID和接受者ID列表
其他的发挥自己的想象力去想啦

#2


使用完成端口才四个线程!还是换成别的吧。

#3


完成端口的优点之一是能够发挥多处理器的优势,如果能够每个处理器刚好一个线程正在运行,那就最好不过了。所以,四个,或者十个线程并不能代表什么。1000个线程也不代表着就好。

#4


我这里要问的问题不是几个线程的问题,我只是举个例子假如有4个线程。多少个线程与我的问题没有任何关系。我的问题是如何实现信息的转发???

#5


网络游戏在用户登陆的时候就记录下了相关的IP,端口等信息了,比如可以保存在一个数据库里面(我是说可能)这样,任何作为通讯的线程就访问这个数据库,找到相关信息不就行了?!似乎没有什么难以理解的吧?
不过我没有做过网游,也不知道是不是真的这样,但应该没有什么高深的理论。

#6


是tcp的连接呀,你要保存这个ip,和port有什么用呢?呵呵
还是保存连接的哪个socket。

#7


struct
{
  socket s;
  Client c;
。。。
}SOCKOBJ;

从SOCKOBJ的容器中找出相应的客户端,实现转发

#8


HANDLE CreateIoCompletionPort (
  HANDLE FileHandle,              // handle to file
  HANDLE ExistingCompletionPort,  // handle to I/O completion port
  ULONG_PTR CompletionKey,        // completion key
  DWORD NumberOfConcurrentThreads // number of threads to execute concurrently
);
第一个参数是Accept出来的socket句柄
第二个参数是完成端口句柄
第三个参数可以放任意的自定义指针,例如可以放一结构体指针
结构体可以这样定义:
typedef struct _CompleteKey
{
SOCKET sSocket;// socket句柄
int nUserId;// 用户id
......
}CompleteKey;
这样就可以识别了
看看书吧<<windows网络编程技术>>第8章,很简单.

#9


nightlocus(英雄本色) ( ) 信誉:100 

是tcp的连接呀,你要保存这个ip,和port有什么用呢?呵呵
还是保存连接的哪个socket。
------------------------------------------------------

支持该方法!
我现在也正在写一个消息转发程序
这个问题也想了很久
后来我也是用一个队列将客户端的socket保存起来,当然与用户ID构成了一个类
也就是说用一类或结构保存客户标识和连接的socket。

也不知还有其他什么好方法没有

楼下的继续...

#10


同意飞的做法,这应该是正确的解决办法

#11


to Fly1980(飞) :
  我想请问一下,我定义了第三个参数的结构体变量,这个变量能让多个连接共用吗?

#12


在服务器上,使用accept接受客户端的一个连接后,此函数的返回值就是一个socket值,这个值就是服务器与客户端通信的信道,你想要向哪个客户端发数据,只要在send时把SOCKET值赋成相对应的客户端就行了。这里有个问题,即在网络层上,没办法区分是哪一个客户端,你必须使用自己的协议由客户端向服务器端发送一个包,这个包用于作为客户端的标识,比如在连接之后,发一个自己的用户名给服务器,这样服务器就可以把这个端口和这个用户名对应起来,而你此后想对哪一个客户端发消息,就根据记录的用户名列表查他所对应的端口就行了。

#13


to 亚飞:
好久不见,甚是想念。

使用数据库记录这样的信息是不可取的,因为在服务器的诸多控制中,会多次使用到这个端口信息,一般是建立一个HASH表来存取,速度快。

#14


to intraweb(★人贱人爱★):
第三个参数本来就是为了识别客户,为什么还要公用??
正确的方法是有一个容器存放第三个参数集合(也就是客户集合),例如数组.
每accept出来一个客户时就new一个结构体,并加入到容器中.
当与客户对应的socket上有信号(读完成,写完成...)时,就能够取到对应的结构体指针.
这样就可以做任何事情了..

#15


说来说去就是要自己建立一个 Session Pool ,内存中的, 就象 ASP.Net 和 JSP 实现的那样, 不过它们更复杂,而楼主这个比较简单。

关于 完成端口 的完美运用,建议大家看看 CodeProject 上的那个 JetByteTools,堪称经典!

BTW:
HANDLE CreateIoCompletionPort (
  HANDLE FileHandle,              // handle to file
  HANDLE ExistingCompletionPort,  // handle to I/O completion port
  ULONG_PTR CompletionKey,        // completion key
  DWORD NumberOfConcurrentThreads // number of threads to execute concurrently
);
表面上看第一个参数是 handle to file,但不要误解,完成端口可以控制任何资源的,如:硬盘文件、网络Socket端口,JetByteTools 简直是把它运用得炉火纯青,是居家旅行之必备良药……

#16


请问楼上的哪里有卖丫?