📄 pipe_imp.c
字号:
// First the #includes.#include "cd_data.h"#include "cliserv.h"// We also define some values that we need in different functions within the file.static int server_fd = -1;static pid_t mypid = 0;static char client_pipe_name[PATH_MAX + 1] = {'\0'};static int client_fd = -1;static int client_write_fd = -1;// The server_starting routine creates the named pipe from which the server will read commands.// It then opens it for reading. This open will block until a client opens the pipe for writing.// We use a blocking mode, so that the server can perform blocking reads on the pipe while// waiting for commands to be sent to it.int server_starting(void){ #if DEBUG_TRACE printf("%d :- server_starting()\n", getpid()); #endif unlink(SERVER_PIPE); if (mkfifo(SERVER_PIPE, 0777) == -1) { fprintf(stderr, "Server startup error, no FIFO created\n"); return(0); } if ((server_fd = open(SERVER_PIPE, O_RDONLY)) == -1) { fprintf(stderr, "Server startup error, no FIFO opened\n"); return(0); } return(1);}// When the server ends, it removes the named pipe, so clients can detect that no server// is running.void server_ending(void){ #if DEBUG_TRACE printf("%d :- server_ending()\n", getpid()); #endif (void)close(server_fd); (void)unlink(SERVER_PIPE);}// The read_request_from_client function, shown below, will block reading the server pipe// until a client writes a message into it.int read_request_from_client(message_db_t *rec_ptr){ int return_code = 0; int read_bytes; #if DEBUG_TRACE printf("%d :- read_request_from_client()\n", getpid()); #endif if (server_fd != -1) { read_bytes = read(server_fd, rec_ptr, sizeof(*rec_ptr)); // In the special case when no clients have the pipe open for writing, the read will return 0,// i.e. it detects an EOF.// Then the server closes the pipe and opens it again, so that it blocks until a client also// opens the pipe.// This is just the same as when the server first starts; we have re-initialized the server.// Insert this code in the function above. if (read_bytes == 0) { (void)close(server_fd); if ((server_fd = open(SERVER_PIPE, O_RDONLY)) == -1) { fprintf(stderr, "Server error, FIFO open failed\n"); return(0); } read_bytes = read(server_fd, rec_ptr, sizeof(*rec_ptr)); } if (read_bytes == sizeof(*rec_ptr)) return_code = 1; } return(return_code);}// First, we open the client pipe.int start_resp_to_client(const message_db_t mess_to_send){ #if DEBUG_TRACE printf("%d :- start_resp_to_client()\n", getpid()); #endif (void)sprintf(client_pipe_name, CLIENT_PIPE, mess_to_send.client_pid); if ((client_fd = open(client_pipe_name, O_WRONLY)) == -1) return(0); return(1);}// The messages are all sent using calls to this function.// We'll look at the corresponding client-side functions that field the message soon.int send_resp_to_client(const message_db_t mess_to_send){ int write_bytes; #if DEBUG_TRACE printf("%d :- send_resp_to_client()\n", getpid()); #endif if (client_fd == -1) return(0); write_bytes = write(client_fd, &mess_to_send, sizeof(mess_to_send)); if (write_bytes != sizeof(mess_to_send)) return(0); return(1);}// Finally, we close the client pipe.void end_resp_to_client(void){ #if DEBUG_TRACE printf("%d :- end_resp_to_client()\n", getpid()); #endif if (client_fd != -1) { (void)close(client_fd); client_fd = -1; }}// After checking that a server is accessible, the client_starting function initializes// the client-side pipe.int client_starting(void){ #if DEBUG_TRACE printf("%d :- client_starting\n", getpid()); #endif mypid = getpid(); if ((server_fd = open(SERVER_PIPE, O_WRONLY)) == -1) { fprintf(stderr, "Server not running\n"); return(0); } (void)sprintf(client_pipe_name, CLIENT_PIPE, mypid); (void)unlink(client_pipe_name); if (mkfifo(client_pipe_name, 0777) == -1) { fprintf(stderr, "Unable to create client pipe %s\n", client_pipe_name); return(0); } return(1);}// The client_ending function closes file descriptors and deletes the now redundant named pipe.void client_ending(void){ #if DEBUG_TRACE printf("%d :- client_ending()\n", getpid()); #endif if (client_write_fd != -1) (void)close(client_write_fd); if (client_fd != -1) (void)close(client_fd); if (server_fd != -1) (void)close(server_fd); (void)unlink(client_pipe_name);}// The send_mess_to_server function passes the request through the server pipe.int send_mess_to_server(message_db_t mess_to_send){ int write_bytes; #if DEBUG_TRACE printf("%d :- send_mess_to_server()\n", getpid()); #endif if (server_fd == -1) return(0); mess_to_send.client_pid = mypid; write_bytes = write(server_fd, &mess_to_send, sizeof(mess_to_send)); if (write_bytes != sizeof(mess_to_send)) return(0); return(1);}// This client function starts to listen for the server response.// It opens a client pipe as read-only and then reopens this pipe's file as write-only.// We'll see why in a moment.int start_resp_from_server(void){ #if DEBUG_TRACE printf("%d :- start_resp_from_server()\n", getpid()); #endif if (client_pipe_name[0] == '\0') return(0); if (client_fd != -1) return(1); client_fd = open(client_pipe_name, O_RDONLY); if (client_fd != -1) { client_write_fd = open(client_pipe_name, O_WRONLY); if (client_write_fd != -1) return(1); (void)close(client_fd); client_fd = -1; } return(0);}// Here's the main read from the server which gets the matching database entries.int read_resp_from_server(message_db_t *rec_ptr){ int read_bytes; int return_code = 0; #if DEBUG_TRACE printf("%d :- read_resp_from_server()\n", getpid()); #endif if (!rec_ptr) return(0); if (client_fd == -1) return(0); read_bytes = read(client_fd, rec_ptr, sizeof(*rec_ptr)); if (read_bytes == sizeof(*rec_ptr)) return_code = 1; return(return_code);}// And finally, the client function that marks the end of the server response.void end_resp_from_server(void){ #if DEBUG_TRACE printf("%d :- end_resp_from_server()\n", getpid()); #endif /* This function is empty in the pipe implementation */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -