c-在两个不同的套接字接口上侦听的服务器程序



TCP服务器程序是否可以侦听两个不同的套接字接口?

问题说明:

我有一个问题声明,TCP服务器将有两个接口:

  • 接口I:用于接受来自TCP客户端的通用数据(IP地址192.168.5.10:2000)
  • 接口II:服务器的管理接口(IP地址192.168.5.11:2000)

接口I:该接口应接收来自TCP客户端的数据,并对其进行处理;将其发送回客户端。

接口II:该接口应接收命令(用于服务器管理)。这些命令很可能通过telnet发送。

当前状态:我已经有了一个基于线程的TCP服务器程序,其中我有">接口I";运行(我能够从多个客户端接收数据,处理它们并将其发回)

有人能给我一些关于如何将"Interface II">添加到我的TCP服务器程序的指针/原型示例吗?

注意:TCP服务器程序是用Linux操作系统的C编程语言编写的

更新

以下是我迄今为止为监听一个套接字而编写的代码片段。我试着按照您的指示修改它以监听两个套接字,但在尝试为另一个套接字接口生成不同的线程时遇到了麻烦。您是否可以将其修改为在两个套接字上侦听?这真的很有帮助。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
void *data_processing_thread(void *arg);
int main(int argc, char **argv) 
{
int fdmax, listener, newfd, res;
int optval=1;
socklen_t addrlen;
int server_port = 4000;
/* master, temp file descriptor list */
fd_set *master, *read_fds;
/* client, server address */
struct sockaddr_in server_addr, client_addr;
pthread_t thread;
master = malloc(sizeof(fd_set));
read_fds = malloc(sizeof(fd_set));
FD_ZERO(master);
FD_ZERO(read_fds);
/* create endpoint for communication */
if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("failed to create listenern");
return -1; 
}
/* check if address is already in use? */
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &optval,
sizeof(int)) == -1) { 
perror("socket address already in use!n");
return -1;
}
/* bind */
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(server_port);
memset(&(server_addr.sin_zero), '', 8);
if (bind(listener, (struct sockaddr*)&server_addr,
sizeof(server_addr)) == -1) {
perror("failed to do the bindn");
return -1;
}
/* listen for connect on sockets */
if (listen(listener, 10) == -1) {
perror("failed to listen on socketn");
return -1;
}
/* add the listener to the master set */
FD_SET(listener, master);
/* keep track of biggest file descriptor */
fdmax = listener;
while (1) {
read_fds = master;
/* wait till socket descriptor is ready for the operation */
if (select(fdmax+1, read_fds, NULL, NULL, NULL) == -1) {
perror("failed to do select() on socketn");
return -1;
}
/* Run through existing data connections looking for data to be
* read */
int cnt;
int *accept_fd = 0;
for (cnt=0; cnt<=fdmax; cnt++) {
if (cnt == listener) {
if (FD_ISSET(cnt, read_fds)) {
addrlen = sizeof(client_addr);
if ((newfd = accept(listener, (struct sockaddr*)&client_addr, &addrlen)) == -1) {
perror("failed to accept incoming connectionn");
} else {
fprintf(stdout, "Server: Connection from client [%s] on socket [%d]n",
inet_ntoa(client_addr.sin_addr), newfd);
accept_fd = malloc(sizeof(int));
*accept_fd = newfd;
if ((res = pthread_create(&thread, NULL, data_processing_thread, (void*)accept_fd)) != 0) {
perror("Thread creation failedn");
free(accept_fd);
}
}
}
continue;
}
}
}
return 1;
}
void *data_processing_thread(void *arg)
{
int nbytes;
int *recv_fd = (int*)arg;
char *buffer = malloc(sizeof(char)*256);
while(1) {
fprintf(stdout, "Server: Waiting for data from socket fd %dn", *recv_fd);
/* receive incoming data from comm client */
if ((nbytes = recv(*recv_fd, buffer, sizeof(buffer), 0)) <= 0) {
if (nbytes != 0) {
perror("failed to receiven");
}
break;
} else {
fprintf(stdout, "Data received: %sn", buffer);
}
}
close(*recv_fd);
free(recv_fd);
pthread_exit(0);
}
  1. 使用socket()创建两个侦听套接字
  2. 使用bind()将两者绑定到各自的地址/端口
  3. 使用listen()使两者都侦听
  4. 使用FD_SET()将两个侦听套接字添加到正确初始化的fd_set类型变量中
  5. fd_set传递给对select()的调用
  6. select()返回后,检查原因并执行适当的操作,通常是

    • 在两个侦听套接字中的一个上调用accept(),并将接受的套接字(由accept()返回)添加到fd_set

    • 或者,如果是一个已接受的套接字触发了select()的返回,则调用其上的read()write()close()。如果close()正在使用该套接字,则使用FD_CLR()将其从fd_set中删除。

  7. 从第5步开始。

重要提示:上面的步骤是一个粗略的方案,没有提到所有可能的陷阱,因此绝对有必要仔细阅读每个步骤的相关手册页,以了解发生了什么。

您可以绑定0.0.0.0,这意味着绑定所有接口。不能只使用一个套接字绑定两个接口。您应该创建一个新的套接字,并将ti绑定到接口II。

最新更新