我正在使用套接字在C中创建客户端/服务器程序。服务器必须能够处理许多客户端。
正确设置服务器后,客户端连接到服务器,并发送“Ready”或“Kill”。服务器接收消息,并回复“Go”或“Destroy”。
如果客户端收到的回复是“Go”,则执行参数传递的命令。该命令执行如下:system(command)
如果客户收到的回复是“销毁”,则客户端将关闭,服务器将被销毁。
服务器必须能够处理许多客户端,但它必须允许一次只有一个客户端执行命令。此外,如果客户端连接到服务器并发送“Kill”,则必须关闭队列中的所有客户端,并且必须立即销毁服务器。
所以,要实现这一点,我正在使用select()
所以我遇到了这个规范的问题:它必须允许一次只有一个客户端执行命令。
基本上,该命令在客户端执行。我不希望两个客户端能够同时执行命令。
这是一个例子(这不是代码):
Client1 : system(echosleep hello1 goodbye1);
Client2 : system(echosleep hello2 goodbye2);
所以我的程序现在正常工作,打印出来:
hello1
hello2
goodbye1
goodbye2
但我想要的是:
hello1
goodbye1
hello2
goodbye2
- >我不明白服务器如何知道命令是否完成,因为它是在客户端执行的。
所以这是我的服务器代码结构(我不是在这里发布完整的代码,因为我的问题不是编写代码本身,而是更多关于结构,以及我应该在哪里发送“Go”到客户端..所以我遗漏了不相关的代码):
//initialize all client_socket[] to 0
//Create master_socket
//bind() master_socket
//listen() master_socket
//accept the incoming connection
addrlen = sizeof(address);
while(TRUE) {
//clear the socket set
FD_ZERO(&readfds);
//add master socket to set
FD_SET(master_socket, &readfds);
max_sd = master_socket;
//add child sockets to set
for ( i = 0 ; i < max_clients ; i++) {
//socket descriptor
sd = client_socket[i];
//if valid socket descriptor then add to read list
if(sd > 0) {
FD_SET( sd , &readfds);
}
//highest file descriptor number, need it for the select function
if(sd > max_sd) {
max_sd = sd;
}
}
//wait for an activity on one of the sockets , timeout is NULL , so wait indefinitely
activity = select( max_sd + 1 , &readfds , NULL , NULL , NULL);
if (activity < 0) {
printf("select()");
}
//If something happened on the master socket , then its an incoming connection
if (FD_ISSET(master_socket, &readfds)) {
if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {
perror("accept()");
return -1;
}
//Check message received from the Client
//if message == Kill then destroy everything (this is working)
//if message == Ready, then send Go
//When the Client receives Go, it will proceed with the execution of his command
//add Client to the queue
for (i = 0; i < max_clients; i++) {
//if position is empty
if( client_socket[i] == 0 ) {
client_socket[i] = new_socket;
break;
}
}
}
}
答案 0 :(得分:1)
我不明白服务器如何知道该命令是否存在 完成与否
简单的答案是,它不能,正是因为你提到的原因。除非客户端告诉客户端,否则服务器无法知道客户端内部发生了什么。
因此,该问题的一个解决方案是在客户端完成命令之后让客户端将另一个消息(例如“完成”)发送回服务器。收到“完成”消息后,服务器将知道客户端已完成执行,然后可以在另一个客户端上授权另一个命令(如果有)。
(btw让客户端从网络接收字符串并将该字符串传递给system()是一个很大的潜在安全漏洞 - “邪恶”服务器可以传递像“rm -rf *”这样的字符串并导致您的客户端删除所有文件!在学术背景之外运行客户端软件时要小心)