我有一个用C写的服务器,它在功能accept()
处被阻塞并等待新的传入连接。当新连接被接受时,它通过调用fork()
创建一个新进程。我不使用epoll
,因为每个客户端套接字都由独立进程处理,并且它使用的库之一在多线程环境中崩溃。套接字编程:accept()延迟
这里是服务器的代码:
srv_sock = init_unix_socket();
listen(srv_sock, 5);
/* Other code which handles SIGCLD. */
while (1) {
log_info("Awaiting new incoming connection.");
clt_sock = accept(srv_sock, NULL, NULL);
if (clt_sock < 0) {
log_err("Error ...");
continue;
}
log_info("Connection %d accepted.", clt_sock);
cld_pid = fork();
if (cld_pid < 0) {
log_err("Failed to create new process.");
close(clt_sock);
continue;
}
if (clt_pid == 0) {
/* Initialize libraries. */
/* Handle client connection ... */
shutdown(clt_sock, SHUT_RDWR);
close(clt_sock);
_exit(0);
}
else {
log_info("Child process created for socket %d.", clt_sock);
close(clt_sock);
}
}
客户端是用Java编写的,它通过使用图书馆junixsocket
,因为Java不支持Unix域套接字连接到服务器。当它连接到服务器时,它会发送一个请求(一个头文件+ XML文档)并等待服务器的回复。
下面是客户端的代码:
File socketFile = new File(UNIX_SOCKET_PATH);
AFUNIXSocket socket = AFUNIXSocket.newInstance();
socket.connect(new AFUNIXSocketAddress(socketFile));
InputStream sis = socket.getInputStream();
OutputStream sos = socket.getOutputStream();
logger.info("Connected with server.");
byte[] requestHeader;
byte[] requestBuffer;
sos.write(requestHeader, 0, requestHeader.length);
logger.info("Header sent.");
sos.write(requestBuffer, 0, requestBuffer.length);
logger.info("Request XML sent.");
sos.flush();
现在的问题是,当我有在同一时间连接到服务器3个客户端线程。我总是有1个任务正在运行,另外2个任务正在等待,直到第一个任务完成。
我检查了日志。所有3个客户线程都已经(几乎)同时连接并向服务器发送请求,但服务器只接受了第一个到达的服务器,并延迟了其他两个线程。根据日志,客户端上的connect
与服务器端上的accept
之间有3分钟的延迟。
起初我以为延迟可能是由某种缓冲区引起的,所以我在每次调用OutputStream.write
之后调用OutputStream.flush()
,但问题依然存在。
我不明白什么可能会导致此延迟,请任何想法吗?
谢谢。
更新2016年3月15日
pstack
表明,父进程在我的SIGCHLD
处理器受阻于waitpid
。这很可能是为什么accept
在新的传入连接到达时没有返回,因为执行过程被信号处理程序中断。
这里是我的信号处理程序的代码:
static void _zombie_reaper (int signum) {
int status;
pid_t child;
if (signum != SIGCHLD) {
return;
}
while ((child = waitpid(-1, &status, WNOHANG)) != -1) {
continue;
}
}
/* In main function */
struct sigaction sig_act;
memset(&sig_act, 0, sizeof(struct sigaction));
sigemptyset(&sig_act.sa_mask);
sig_act.sa_flags = SA_NOCLDSTOP;
sig_act.sa_handler = _zombie_reaper;
if (sigaction(SIGCHLD, &sig_act, NULL) < 0) {
log_err("Failed to register signal handler.");
}
C服务器端的代码在哪里?这将是这类问题的第一个嫌疑犯。没有任何代码就很难解决这个问题。 –
对不起@AnttiHaapala,我已经添加了服务器代码。 – vesontio
Upvoted。到目前为止,我看不出任何错误的服务器代码:(如何日志输出,是否有'等待新的传入连接.'和'接受连接'之间3分钟的延迟?也许它是在客户端然后 –