我要写一个TCP服务器(Socket - Linux - C)。我有三个问题:
1)要知道网络(或连接)是否已关闭,我是否使用SO_KEEPALIVE
选项?
例如:
int optval = 1;
socklen_t optlen = sizeof(optval);
if (setsockopt(file_descriptor,SOL_SOCKET,SO_KEEPALIVE,&optval,optlen)<0) {
Close(file_descriptor);
Print_error("setsockopt() failed");
2)我希望我的服务器联系其他服务器。我的服务器如何知道远程服务器是否关闭?
3)我想写一个并发服务器,因此我使用fork()
来创建子项:
3.1)我必须处理对共享变量的并发访问,即使它们仅用于读取目的吗?
3.2)我的进程列表中不会有僵尸......这段代码可以正确吗?
void sigchld_h (int signum);
int main(int argc, char *argv[]){
...;
}
void sigchld_h (int signum){
pid_t pid;
int status;
while ( (pid = waitpid(-1,&status,WNOHANG)) > 0)
printf("(%s) INFO - child %d terminated with exit status %d", nome_programma, pid, status);
}
非常感谢您的咨询。
答案 0 :(得分:3)
要知道网络(或连接)是否已关闭,我是否使用SO_KEEPALIVE选项?
你可以做到这一点。或者,您可以在TCP / IP之上实现自己的“心跳”机制。
我希望我的服务器与其他服务器联系。我的服务器如何知道远程服务器是否关闭?
服务器无法连接到其他服务器。连接的人是客户。接受的是服务器。无论如何,您必须使用心跳机制并处理错误以确定服务器何时停机(意外)。
我想写一个并发服务器,所以我使用fork()来创建子
这几乎是每个案例中最糟糕的想法。执行此操作的最佳方法是使用线程数相当少的asynchronous I/O。
我必须处理对共享变量的并发访问,即使它们仅用于读取目的吗?
如果使用fork()
,每个进程都会收到自己的内存副本,其中包含变量,因此不需要同步。如果是线程,则在访问只读内存时无需锁定。
我的进程列表中不会有僵尸......这段代码可以正确吗?
不,您不能从信号处理程序中调用printf()
。只允许异步/重入安全功能。
答案 1 :(得分:1)
SO_KEEPALIVE
可帮助您确定给定的TCP连接已死,这意味着另一方在给定时间内(通常为2小时)没有活动。它还有助于通过中间路由器维护空闲的TCP连接,这些中间路由器可能由于不活动而暂停连接状态。例如,请参阅here以获得更长的解释。在这种情况下,您的服务器充当客户端。连接到远程端并交换数据。如果你a)无法连接,或者b)接收零字节(对等端正常关闭套接字),或者c)从send(2)
收到错误说管道坏了,你就会知道对方已关闭。同样,远程服务器崩溃是最难检测的。 SO_KEEPALIVE
最终会告诉您有问题,但应用程序心跳会更快地告诉您。
fork(2)
是现代Unix上最重的并发工具。基于每个客户端连接的子进程(甚至每个连接的线程)的设计很快导致资源问题,并且通常很慢。探索线程池和非阻塞套接字以及select(2)
,poll(2)
和epoll(7)
等轮询机制。