三个问题,以创建一个TCP服务器 - 套接字,Linux与C

时间:2013-06-14 12:26:02

标签: c linux sockets fork

我要写一个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);
}

非常感谢您的咨询。

2 个答案:

答案 0 :(得分:3)

  

要知道网络(或连接)是否已关闭,我是否使用SO_KEEPALIVE选项?

你可以做到这一点。或者,您可以在TCP / IP之上实现自己的“心跳”机制。

  

我希望我的服务器与其他服务器联系。我的服务器如何知道远程服务器是否关闭?

服务器无法连接到其他服务器。连接的人是客户。接受的是服务器。无论如何,您必须使用心跳机制并处理错误以确定服务器何时停机(意外)。

  

我想写一个并发服务器,所以我使用fork()来创建子

这几乎是每个案例中最糟糕的想法。执行此操作的最佳方法是使用线程数相当少的asynchronous I/O

  

我必须处理对共享变量的并发访问,即使它们仅用于读取目的吗?

如果使用fork(),每个进程都会收到自己的内存副本,其中包含变量,因此不需要同步。如果是线程,则在访问只读内存时无需锁定。

  

我的进程列表中不会有僵尸......这段代码可以正确吗?

不,您不能从信号处理程序中调用printf()。只允许异步/重入安全功能。

答案 1 :(得分:1)

  1. SO_KEEPALIVE可帮助您确定给定的TCP连接已死,这意味着另一方在给定时间内(通常为2小时)没有活动。它还有助于通过中间路由器维护空闲的TCP连接,这些中间路由器可能由于不活动而暂停连接状态。例如,请参阅here以获得更长的解释。

    了解关联对等体状态的更有用,更方便的方法是在应用程序级协议中建立定期心跳交换。

  2. 在这种情况下,您的服务器充当客户端。连接到远程端并交换数据。如果你a)无法连接,或者b)接收零字节(对等端正常关闭套接字),或者c)从send(2)收到错误说管道坏了,你就会知道对方已关闭。同样,远程服务器崩溃是最难检测的。 SO_KEEPALIVE最终会告诉您有问题,但应用程序心跳会更快地告诉您。

  3. fork(2)是现代Unix上最重的并发工具。基于每个客户端连接的子进程(甚至每个连接的线程)的设计很快导致资源问题,并且通常很慢。探索线程池非阻塞套接字以及select(2)poll(2)epoll(7)等轮询机制。