我有 Status Bar Cocoa App ,它为我的后台运行服务器提供GUI以及常规信息和首选项窗口。这个服务器是用C编程语言实现的,它现在唯一的工作就是对客户端进行简单的回显。
应用程序具有启动此服务器的按钮。当我按下此按钮时,服务器启动并侦听随机选择的端口。它工作正常,我甚至可以重启服务器等。
我使用此代码启动服务器:
- (void) startServerInBackground: (server_t) serverFunc {
dispatch_queue_t server_dispatch_queue = dispatch_queue_create("click.remotely.Server", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(server_dispatch_queue, ^(void){
start_server(serverFunc, serverInfo);
/***
* dispatch_async(dispatch_get_main_queue(), ^(void){
* //Run UI Updates
* });
*/
});
}
只有当某个客户端连接到服务器时,问题才会开始。
我可以使用telnet 192.168.8.101 <PORT_NUMBER>
进行连接。我甚至可以与服务器通话,它可以正确重放。这里奇怪的事情发生了!
当我尝试打开Status Bar Cocoa App时,我可能会遇到如下崩溃: 1.很长时间没有崩溃(客户端与服务器通信,重启,切换窗口和窗格) 2.连接客户端并选择App的状态栏图标后立即崩溃 3.稍后当我连接客户端,打开状态栏图标,选择一些菜单项并尝试打开窗口时崩溃。 该应用程序也会在稍后崩溃。不是在第一个窗口打开,而是第三,第四或第n个窗口打开,按钮单击。
导致应用崩溃的原因是什么?我该如何解决这个问题?
这是我在C
中的服务器循环/**
* Function is looping infinitely and waiting
* for new incoming client connections.
* It handles connections one by one on the same thread.
*/
result_t iterative_stream_server_loop(server_info_t *server_info, connection_handler_t handle_connection) {
sock_fd_t cs_fd, ps_fd;
// get passive server socket
ps_fd = server_info_sock(server_info);
while(1) {
if(server_info_should_shut_down(server_info)) {
return CLOSED;
}
if(server_info_force_shut_down(server_info)) {
return FORCE_CLOSED;
}
// check to accept new connection on the main thread...
cs_fd = accept_new_connection(ps_fd);
if(cs_fd == FAILURE) {
fprintf(stderr, "accept_new_connection: failed!\n");
server_info_connection_error_event(server_info, cs_fd, CONN_ERROR_ACCEPT, "accept_new_connection: failed!");
return FAILURE;
} else if(cs_fd == CONTINUE) {
continue;
}
// publish client connected event
server_info_client_connected_event(server_info, cs_fd);
printf("Handle connection on the main thread...\n");
switch (handle_connection(server_info, cs_fd)) {
case FAILURE:
fprintf(stderr, "handle_connection: failed!\n");
// publish connection error event
server_info_connection_error_event(server_info, cs_fd, CONN_ERROR_HANDLER, "handle_connection: failed!");
break;
case CLOSED:
printf("handle_connection: closed!\n");
// publish client disconnecting event
server_info_client_disconnecting_event(server_info, cs_fd);
break;
default:
break;
}
if(close(cs_fd) < 0){
fprintf(stderr, "close: %s\n", strerror(errno));
server_info_connection_error_event(server_info, cs_fd, CONN_ERROR_CLOSE, strerror(errno));
return FAILURE;
}
}
}
这是客户端连接处理(回显服务)
result_t echo_service_connection_handler(server_info_t *server_info, sock_fd_t sock_fd) {
char buf[MAX_BUF_SIZE];
int n_recv; // number of bytes received
int n_sent; // number of bytes sent
fcntl(sock_fd, F_SETFL, O_NONBLOCK);
while(1) {
if(server_info_should_shut_down(server_info))
return CLOSED;
if ((n_recv = recv(sock_fd, buf, sizeof(buf) - 1, 0)) <= 0) {
if(n_recv == 0) {
printf("echo connection is closing...\n");
return CLOSED;
}
if( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
// call to recv() on non-blocking socket result with nothing to receive
continue;
}
perror("recv");
// publish connection error event
server_info_connection_error_event(server_info, sock_fd, CONN_ERROR_RECV, strerror(errno));
return FAILURE;
}
buf[n_recv] = '\0';
printf(ANSI_COLOR_BLUE "server: received '%s'" ANSI_COLOR_RESET "\n", buf);
if ((n_sent = send(sock_fd, buf, strlen(buf), 0)) < 0) {
perror("send");
// publish connection error event
server_info_connection_error_event(server_info, sock_fd, CONN_ERROR_SEND, strerror(errno));
return FAILURE;
}
}
return SUCCESS;
}