📄 clientif.c
字号:
// The file starts with #include files and constants.#define _POSIX_SOURCE#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#include "cd_data.h"#include "cliserv.h"// The static variable mypid reduces the number of calls to getpid that would// otherwise be required.// We use a local function, read_one_response, to eliminate duplicated code.static pid_t mypid;static int read_one_response(message_db_t *rec_ptr);// The database_initialize and close routines are still called, but are now used, respectively,// for initializing the client-side of the pipes interface and for removing redundant named// pipes when the client exits.int database_initialize(const int new_database){ if (!client_starting()) return(0); mypid = getpid(); return(1); } /* database_initialize */void database_close(void) { client_ending();}// The get_cdc_entry routine is called to get a catalog entry from the database,// given a CD catalog title.// Here we encode the request in a message_db_t structure and pass it to the server.// We then read the response back into a different message_db_t structure.// If an entry is found, it's included inside the message_db_t structure as a cdc_entry// structure, so we pass back the appropriate part of the structure.cdc_entry get_cdc_entry(const char *cd_catalog_ptr){ cdc_entry ret_val; message_db_t mess_send; message_db_t mess_ret; ret_val.catalog[0] = '\0'; mess_send.client_pid = mypid; mess_send.request = s_get_cdc_entry; strcpy(mess_send.cdc_entry_data.catalog, cd_catalog_ptr); if (send_mess_to_server(mess_send)) { if (read_one_response(&mess_ret)) { if (mess_ret.response == r_success) { ret_val = mess_ret.cdc_entry_data; } else { fprintf(stderr, "%s", mess_ret.error_text); } } else { fprintf(stderr, "Server failed to respond\n"); } } else { fprintf(stderr, "Server not accepting requests\n"); } return(ret_val);}// Here's the source for the function read_one_response that we use to avoid duplicating code.static int read_one_response(message_db_t *rec_ptr) { int return_code = 0; if (!rec_ptr) return(0); if (start_resp_from_server()) { if (read_resp_from_server(rec_ptr)) { return_code = 1; } end_resp_from_server(); } return(return_code);} // The other get_xxx, del_xxx and add_xxx routines are implemented in a similar way to the// get_cdc_entry function and are reproduced here for completeness.// First, the function for retrieving CD tracks.cdt_entry get_cdt_entry(const char *cd_catalog_ptr, const int track_no){ cdt_entry ret_val; message_db_t mess_send; message_db_t mess_ret; ret_val.catalog[0] = '\0'; mess_send.client_pid = mypid; mess_send.request = s_get_cdt_entry; strcpy(mess_send.cdt_entry_data.catalog, cd_catalog_ptr); mess_send.cdt_entry_data.track_no = track_no; if (send_mess_to_server(mess_send)) { if (read_one_response(&mess_ret)) { if (mess_ret.response == r_success) { ret_val = mess_ret.cdt_entry_data; } else { fprintf(stderr, "%s", mess_ret.error_text); } } else { fprintf(stderr, "Server failed to respond\n"); } } else { fprintf(stderr, "Server not accepting requests\n"); } return(ret_val);}// Next, two functions for adding data, first to the catalog and then to the tracks database.int add_cdc_entry(const cdc_entry entry_to_add){ message_db_t mess_send; message_db_t mess_ret; mess_send.client_pid = mypid; mess_send.request = s_add_cdc_entry; mess_send.cdc_entry_data = entry_to_add; if (send_mess_to_server(mess_send)) { if (read_one_response(&mess_ret)) { if (mess_ret.response == r_success) { return(1); } else { fprintf(stderr, "%s", mess_ret.error_text); } } else { fprintf(stderr, "Server failed to respond\n"); } } else { fprintf(stderr, "Server not accepting requests\n"); } return(0);}int add_cdt_entry(const cdt_entry entry_to_add){ message_db_t mess_send; message_db_t mess_ret; mess_send.client_pid = mypid; mess_send.request = s_add_cdt_entry; mess_send.cdt_entry_data = entry_to_add; if (send_mess_to_server(mess_send)) { if (read_one_response(&mess_ret)) { if (mess_ret.response == r_success) { return(1); } else { fprintf(stderr, "%s", mess_ret.error_text); } } else { fprintf(stderr, "Server failed to respond\n"); } } else { fprintf(stderr, "Server not accepting requests\n"); } return(0);}// And lastly, two functions for data deletion.int del_cdc_entry(const char *cd_catalog_ptr){ message_db_t mess_send; message_db_t mess_ret; mess_send.client_pid = mypid; mess_send.request = s_del_cdc_entry; strcpy(mess_send.cdc_entry_data.catalog, cd_catalog_ptr); if (send_mess_to_server(mess_send)) { if (read_one_response(&mess_ret)) { if (mess_ret.response == r_success) { return(1); } else { fprintf(stderr, "%s", mess_ret.error_text); } } else { fprintf(stderr, "Server failed to respond\n"); } } else { fprintf(stderr, "Server not accepting requests\n"); } return(0);}int del_cdt_entry(const char *cd_catalog_ptr, const int track_no){ message_db_t mess_send; message_db_t mess_ret; mess_send.client_pid = mypid; mess_send.request = s_del_cdt_entry; strcpy(mess_send.cdt_entry_data.catalog, cd_catalog_ptr); mess_send.cdt_entry_data.track_no = track_no; if (send_mess_to_server(mess_send)) { if (read_one_response(&mess_ret)) { if (mess_ret.response == r_success) { return(1); } else { fprintf(stderr, "%s", mess_ret.error_text); } } else { fprintf(stderr, "Server failed to respond\n"); } } else { fprintf(stderr, "Server not accepting requests\n"); } return(0);}// This function looks more complicated than it is because it calls three pipe functions// that we'll be looking at in the next section, send_mess_to_server, start_resp_from_server// and read_resp_from_server.cdc_entry search_cdc_entry(const char *cd_catalog_ptr, int *first_call_ptr){ message_db_t mess_send; message_db_t mess_ret; static FILE *work_file = (FILE *)0; static int entries_matching = 0; cdc_entry ret_val; ret_val.catalog[0] = '\0'; if (!work_file && (*first_call_ptr == 0)) return(ret_val);// Here's the first call to search, i.e. with *first_call_ptr set to true.// It's set to false immediately, lest we forget. A work_file is created and the client// message structure initialized. if (*first_call_ptr) { *first_call_ptr = 0; if (work_file) fclose(work_file); work_file = tmpfile(); if (!work_file) return(ret_val); mess_send.client_pid = mypid; mess_send.request = s_find_cdc_entry; strcpy(mess_send.cdc_entry_data.catalog, cd_catalog_ptr);// Now there's this three-deep condition test, which makes calls to functions in pipe_imp.c.// If the message is successfully sent to the server, the client waits for the server's response.// While reads from the server are successful, the search matches are returned to the client's// work_file and the entries_matching counter is incremented. if (send_mess_to_server(mess_send)) { if (start_resp_from_server()) { while (read_resp_from_server(&mess_ret)) { if (mess_ret.response == r_success) { fwrite(&mess_ret.cdc_entry_data, sizeof(cdc_entry), 1, work_file); entries_matching++; } else { break; } } /* while */ } else { fprintf(stderr, "Server not responding\n"); } } else { fprintf(stderr, "Server not accepting requests\n"); }// The next test checks whether the search had any luck.// Then the fseek call sets the work_file to the next place for data to be written. if (entries_matching == 0) { fclose(work_file); work_file = (FILE *)0; return(ret_val); } (void)fseek(work_file, 0L, SEEK_SET);// If this is not the first call to the search function with this particular search term,// the code checks whether there are any matches left. Finally, the next matching entry is// read to the ret_val structure. The previous checks guarantee that a matching entry exists. } else { /* not *first_call_ptr */ if (entries_matching == 0) { fclose(work_file); work_file = (FILE *)0; return(ret_val); } } fread(&ret_val, sizeof(cdc_entry), 1, work_file); entries_matching--; return(ret_val);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -