This program is intended for Linux IPC communication beginners to practice basic concepts such as Message Queue communication mechanism, multi-thread programming, string processing, linked list operation, and simple signal processing in Linux.
Principle:
Message Queue is an IPC Mechanism Supported by System V. By using a linked list-like operation to send user-defined data to a FIFO using msgsnd, the process can receive data similar to mtype through msgrcv, to achieve inter-process communication.
Mainly implements the following functions:
- > Logon through multiple terminals enables private chat for users logging on to different terminals
- > Group chat
- > View online users
- > Simple registration (User saving is not implemented, similar to public chat rooms)
The following describes the process of several operations. For detailed code analysis, see the following blog:
Http://blog.csdn.net/mr_raptor/article/details/8484822
Download Code:
Http://download.csdn.net/detail/mr_raptor/4976808
> The server receives data from the Message Queue through a specific type of mtype: 1000.
> The current login user will randomly generate (random () a random ID number as the applied user ID, and send the application message to the server (mtype = 1000) using the following protocol.
@ Msg. h
The protocol data is defined as follows. There are 4 segments, with ":" As the separator.
// CMD:FROM:TIME:DATA #define DATA_LEN 4#define OFT_CMD 0#define OFT_FRM 1#define OFT_TIM 2#define OFT_DAT 3#define DATA_TOK ":"
CMD: From: Time: Data
CMD: indicates the executed operation.
From: indicates the terminal from
Time: application time
Data: The user sends data.
> After receiving the user application request, the server extracts the available ID from the available ID and assigns the available ID to the new user (the available ID is accumulated from start_id, add it to the linked list maintained by the server, and then write the newly assigned ID number back to the client (use the ID number randomly generated by the client ), in addition, all future communications will use the new ID to act on the mtype of the message queue.
@ Msg. h
#define START_ID 1
> After the login user receives the new ID assigned by the server, the receiving message thread is enabled to wait for receiving the message sent from the message queue to himself.
@ Msg_client.c
if(login() == OK) while(pthread_create(&thread, NULL, receiver_looper, NULL) < 0); break;
void * receiver_looper(void * p){ if(userid == 0) return NULL; char * data[DATA_LEN]; char * str, *subtoken; int i; while(1){ if(msgrcv(msgid, &msg_rcv, sizeof(msg_rcv), userid, 0) < 0){ perror("msgrcv"); continue; }else{
> After receiving a message in the message queue, You can parse the data received by strtok () according to the preceding communication protocol and format the data for branch processing based on different cmd operations.
#ifdef _DEBUG printf("%s received: %s\n", __func__, msg_rcv.buffer);#endif memset(data, NULL, sizeof(data)); for(str = msg_rcv.buffer, i = 0; ; str = NULL, i++){ subtoken = strtok(str, DATA_TOK); if(subtoken == NULL) break; data[i] = subtoken;#ifdef _DEBUG printf("> data[%d] = %s\n", i, subtoken);#endif } // process received data // data format error if(i != DATA_LEN) continue; switch(data[OFT_CMD][0]){ case CMD_LIST: if(strcmp(data[OFT_FRM], TYPE_SERVER_STR)){ continue; } format_user_list(data[OFT_DAT]); break; case CMD_LOGOUT: if(strcmp(data[OFT_FRM], TYPE_SERVER_STR)){ continue; } printf("> %s ", data[OFT_DAT]); printf("%s\n", time2str(atol(data[OFT_TIM]), data[OFT_DAT])); exit(0); case CMD_CHAT: // print chat content printf("\n%s \n\t\t", data[OFT_DAT]); printf("%s\n", time2str(atol(data[OFT_TIM]), data[OFT_DAT])); printf("\n%s# ", name); fflush(stdout); break; case CMD_SEND_FILE: break; } }
> The group chat message is sent to the server. After receiving the message, the server traverses the online linked list and sends the message to each online user.
@ Msg_svr.c
The following is the code snippet of the branch processing:
case CMD_TOALL: // send to all online client p = (&msg_list_head)->next; while(p){ u= (struct user*)p; send_msg(u->id, CMD_CHAT, data[OFT_FRM], data[OFT_DAT]); p = p->next; } break;
Note: This program can only run between different terminals on one host and cannot implement cross-host communication.
The running status is as follows:
Server running status: displays user operations and message forwarding information of the client.
Client Logon: initial help information
User logon and list of online users:
Log on to the luccy user on another terminal to list online users: Private Chat:
Another terminal receives the message: group chat, and both terminals receive the message: Exit: there is also the file transfer function, which is left for the students to implement.