0

我正在用 C 编写一个服务器和两个客户端。一个客户端是接收命令的“从”类型客户端,另一个是发送命令的“主”类型客户端。我希望从服务器的多个实例连接到服务器,并能够通过服务器从主服务器向特定的从服务器发送命令。

我的问题是如何指定要将命令发送到的客户端?

这是我的服务器的一个非常基本的示例(没有错误检查) 我的实际服务器具有错误检查等功能,但是发布时间太长(并且对于任何人都不会编译,因为我的项目中存在对其他文件的依赖项)

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

int server_portnumber = 51739;

int main() {
  int listenFD;
  int connectFD;
  socklen_t length;
  struct sockaddr_in s1;
  struct sockaddr_in s2;

  listenFD = socket( AF_INET , SOCK_STREAM , 0 );
  memset( &s1, 0, sizeof( s1 ) );
  s1.sin_family = AF_INET;
  s1.sin_addr.s_addr = INADDR_ANY;
  s1.sin_port = server_portnumber;

  bind( listenFD , (struct sockaddr*) &s1 , sizeof( s1 ) );

  length = sizeof( s1 );
  getsockname( listenFD ,  (struct sockaddr*) &s1 , &length );
  listen( listenFD , 512 );

  signal( SIGCHLD , SIG_IGN );

  while(1) {
    length = sizeof( s2 );
    connectFD = accept( listenFD , (struct sockaddr*) &s2 , &length );
    if( !fork() ){
      close( listenFD );
      int select = 0;
      while( read( connectFD , &select, sizeof( int ) ) ) {
        switch( select ) {
          case 10:
            // opcode
            break;
          case 20:
            // command
            break;
          default:
            break;
        }
      }
      close( connectFD );
      exit(0);
    }
  }
}
4

1 回答 1

1

您需要为每个客户端分配一个 ID,让 master 以某种方式了解这些 ID,并为服务器提供一些从 ID 映射到套接字的方法。

那个“某种方式”是相当模糊的……因为有无限的可能性,都有不同的设计含义。例如,您可以通过以下方式引用客户:

  • 套接字 fd。
  • 对等地址(主机和端口)。
  • 自动编号的索引。
  • 连接时间。
  • 随机生成的密钥。
  • 在协议中的某个登录步骤期间从客户端收到的密钥。

对于其中的大多数,您必须告诉主服务器有一个具有相关 ID 的新客户端可用。当主服务器想要向特定客户端发送消息时,它会将该 ID 发回,这意味着您将需要某种映射(如果它像 fd 或自动索引这样简单,则只是一个数组;可能是哈希表或平衡树(如果是任意字符串)来查找 ID 并获取 fds。

为了使这一点更具体,请考虑一个聊天协议,如 IRC,但要简单得多。

当您第一次连接时,没有人可以与您交谈,您也无法与其他任何人交谈。

服务器维护一个哈希表来将昵称映射到套接字 fds。

当您发送/nick NICKNAME命令时,NICKNAME有效的昵称在哪里(例如,任何其他人尚未使用的最多 20 个字母和数字的序列),服务器会在哈希表中添加一个条目,将您的昵称映射到您的 fd,并发送一个向所有人说“NICKNAME 加入”的消息。

当您发送/msg NICKNAME MESSAGE命令时,服务器NICKNAME会在哈希表中查找。如果找到它,它会将 MESSAGE 发送到带有相应 fd 的套接字。

于 2013-08-14T00:11:45.573 回答