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



我要写一个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()来创建child:

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);
}

非常感谢您的咨询。

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

你可以那样做。或者,你可以在TCP/IP之上实现你自己的"心跳"机制。

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

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

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

几乎在任何情况下这都是最糟糕的主意。最好的方法是使用异步I/O和相当少的线程数。

我必须处理并发访问共享变量,即使他们只是为了读的目的?

如果您使用fork(),每个进程接收自己的内存副本,其中包括变量,因此不需要同步。在使用线程的情况下,访问只读内存时不需要锁。

我不会在我的进程列表中有僵尸…这个代码是对的吗?

不允许从信号处理程序调用printf()

  1. SO_KEEPALIVE帮助您确定给定的TCP连接已死,这意味着另一方在给定时间(通常为2小时)没有活动。它还有助于通过中间路由器维护空闲的TCP连接,这些中间路由器可能只是由于不活动而使连接状态超时。例如,请参阅此处查看更详细的解释。

    更有用和方便的方法是在应用级协议中构建周期性的心跳交换。

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

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

最新更新