diff --git a/simpleChatting/Makefile b/simpleChatting/Makefile index 5f33c51278b7ad5b47fd99e660ba43538e4ee449..e0c7d7b4a730f78cd46154a0789dfe3a1d46ce31 100644 --- a/simpleChatting/Makefile +++ b/simpleChatting/Makefile @@ -3,22 +3,22 @@ all : client server control CC = gcc client : client.o - $(CC) -o client client.o + $(CC) -o client client.o server : server.o - $(CC) -o server server.o + $(CC) -o server server.o control : control.o - $(CC) -o control control.o + $(CC) -o control control.o client.o : client.c comn.h - $(CC) -c client.c + $(CC) -c client.c server.o : server.c comn.h - $(CC) -c server.c + $(CC) -c server.c control.o : control.c comn.h - $(CC) -c control.c + $(CC) -c control.c clean : - rm client.o server.o control.o client server control \ No newline at end of file + rm client.o server.o control.o diff --git a/simpleChatting/client.c b/simpleChatting/client.c new file mode 100755 index 0000000000000000000000000000000000000000..576b81722a82258e041cedddafb208849066ff67 --- /dev/null +++ b/simpleChatting/client.c @@ -0,0 +1,212 @@ +#include "comn.h" + +void UserConn(); +void UserDisConn(); +void UserChat(); +void UserOut(); + +void setSignal(); + +int main(int argc, char* argv[]) { + + printf("\n[ client process ]\n"); + setSignal(); + shmid = shmget((key_t)0301, sizeof(shData), IPC_EXCL); + if (shmid == -1) { + printf("### no server process ###\n"); + exit(1); + } + + if (shmctl(shmid, IPC_STAT, &info) == -1) { + printf("### shmctl fail ###"); + exit(1); + } + + if (argc < 2) { + printf("### write user name ###\n"); + exit(1); + } + + + printf("user count : %d\n", info.shm_nattch); + + if (info.shm_nattch > 3) { + printf("### max user in. sorry ###\n"); + exit(1); + } + + shmaddr = shmat(shmid, (void*)0, 0); + if (shmaddr == (void*)-1) { + printf("### shmat fail ###\n"); + exit(1); + } + + shData = (struct SharedData*)shmaddr; + + if (strlen(argv[1]) > MAX_USER_NAME) { + printf("### user name max size 10 ###\n"); + exit(1); + } + + int i = 0; + for (i = 0; i < MAX_USER_CNT; i++) { + if (shData->client[i].pid != 0) { + if (strcmp(shData->client[i].name, argv[1]) == 0) { + printf("### [ %s ] is duplicate user name ###\n", argv[1]); + exit(1); + } + } + } + + if (shData->client[0].pid == 0) { + shData->client[0].pid = getpid(); + sprintf(shData->client[0].name, "%s", argv[1]); + } else { + shData->client[1].pid = getpid(); + sprintf(shData->client[1].name, "%s", argv[1]); + } + + pid_t server_pid = shData->pid; + + kill(server_pid, SIGUSR1); + + // message queue create + if ((msqid = msgget((key_t)4225, IPC_CREAT | 0666)) == -1) { + printf("msgget fail\n"); + exit(1); + } + + char msg_buf[MAX_CHAT_LENGTH]; + + printf("=====================\n"); + printf(" user enter chatting\n"); + printf("=====================\n"); + + while (1) { + if ((shData->client[0].pid != 0) && (shData->client[1].pid != 0)) { + memset(chat.message, 0, sizeof(chat.message)); + memset(msg_buf, 0, sizeof(msg_buf)); + + printf("> "); + + fgets(msg_buf, sizeof(msg_buf), stdin); // input buf + + // send user info + chat.send_pid = getpid(); + strcpy(chat.message, msg_buf); + + if (strlen(chat.message) != 0) { + // chat -> message queue + if ((msgsnd(msqid, &chat, sizeof(chat), 0)) == -1) { + printf("### msgsnd fail ###\n"); + exit(1); + } + + // show chat to other user + if (shData->client[0].pid == getpid()) { +// printf("%s> %s\n", shData->client[0].name, msg_buf); + kill(shData->client[1].pid, SIGUSR2); + } else { +// printf("%s> %s\n", shData->client[1].name, msg_buf); + kill(shData->client[0].pid, SIGUSR2); + } + } + } + sleep(1); + } + + return 0; +} + +void UserConn() { + if (shData->client[1].pid == 0) { + printf("\n [ %s ] entered.\n", shData->client[0].name); + } else { + printf("\n [ %s ] entered.\n", shData->client[1].name); + } + printf("-------------------------\n"); +} + +void UserChat() { + // message queue -> chat + if ((msgrcv(msqid, &chat, sizeof(chat), 0, 0)) == -1) { + printf("### msgrcv fail ###\n"); + exit(1); + } + + shData = (struct SharedData*)shmaddr; + + if (chat.send_pid == shData->client[0].pid) { + printf("\n%s >> %s\n", shData->client[0].name, chat.message); + } else { + printf("\n%s >> %s\n", shData->client[1].name, chat.message); + } +} + +void UserDisConn() { + pid_t server_pid = shData->pid; + + if (shmctl(shmid, IPC_STAT, &info) == -1) { + printf("### shmctl fail ###"); + exit(1); + } + + if (info.shm_nattch < 3) { + // message queue delete + if (msgctl(msqid, IPC_RMID, 0) == -1) { + printf("### msgctl fail ###\n"); + exit(1); + } + } + + if (shData->client[0].pid == getpid()) { + shData->client[0].pid = -1; + kill(server_pid, SIGALRM); + kill(shData->client[1].pid, SIGALRM); + printf("\n ### user [ %s ] out ###\n", shData->client[0].name); + exit(1); + } else { + shData->client[1].pid = -1; + kill(server_pid, SIGALRM); + kill(shData->client[0].pid, SIGALRM); + printf("\n### user [ %s ] out ###\n", shData->client[1].name); + exit(1); + } +} + +void UserOut() { + int i = 0; + for (i = 0; i < MAX_USER_CNT; i++) { + if (shData->client[i].pid != getpid()) { + printf("\n ### user [ %s ] out ###\n", shData->client[i].name); + } + } +} + +void setSignal() { + + struct sigaction chat_signal; + struct sigaction conn_sign; + struct sigaction disconn_sign; + struct sigaction leave_signal; + + chat_signal.sa_handler = UserChat; + sigemptyset(&chat_signal.sa_mask); + chat_signal.sa_flags = 0; + sigaction(SIGUSR2, &chat_signal, NULL); + + conn_sign.sa_handler = UserConn; + sigemptyset(&conn_sign.sa_mask); + conn_sign.sa_flags = 0; + sigaction(SIGUSR1, &conn_sign, NULL); + + leave_signal.sa_handler = UserOut; + sigemptyset(&leave_signal.sa_mask); + leave_signal.sa_flags = 0; + sigaction(SIGALRM, &leave_signal, NULL); + + disconn_sign.sa_handler = UserDisConn; + sigemptyset(&disconn_sign.sa_mask); + disconn_sign.sa_flags = 0; + sigaction(SIGINT, &disconn_sign, NULL); +} diff --git a/simpleChatting/comn.h b/simpleChatting/comn.h index de89e9765b29c4b6526ae034b20fdad4e70e741f..54cabdc7eef8875c6e3e86b7b5080c20a6ac8e45 100644 --- a/simpleChatting/comn.h +++ b/simpleChatting/comn.h @@ -1,35 +1,35 @@ #include -#include #include -#include +#include #include +#include +#include #include #include #include +#include #define MAX_USER_CNT 2 #define MAX_USER_NAME 10 #define MAX_CHAT_LENGTH 255 -int isServerConn = -1; +int msqid = 0; int shmid = 0; -void *shmaddr = NULL; -struct shmid_ds info; +void* shmaddr = NULL; // detach shared memory addr +struct shmid_ds info; // buffer pointer with get shared memmory info -typedef struct UserData -{ - int pid; - char name[MAX_USER_NAME]; -}UserData; +struct ClientData { + int pid; + char name[MAX_USER_NAME]; +}; -typedef struct SharedData -{ - int pid; - UserData user[MAX_USER_CNT]; -}SharedData; +struct SharedData { + int pid; + int cliencnt; + struct ClientData client[MAX_USER_CNT]; +} *shData; -typedef struct MessageData -{ - int send_pid; - char content[MAX_CHAT_LENGTH]; -}MsgData; +struct ChatData { + int send_pid; + char message[MAX_CHAT_LENGTH]; +} chat; diff --git a/simpleChatting/control.c b/simpleChatting/control.c new file mode 100755 index 0000000000000000000000000000000000000000..16c29327e25a5b9838a06dff01f2109da31e092a --- /dev/null +++ b/simpleChatting/control.c @@ -0,0 +1,158 @@ +#include "comn.h" + +pid_t pid; + +void connShMemory(); + +int main(int argc, char* argv[]) { + + printf("\n[ control process ]\n\n"); + + connShMemory(); + + // 1. status + if (strcmp(argv[1], "status") == 0) { +// shmid = shmget((key_t)0301, sizeof(shData), IPC_EXCL | IPC_CREAT | 0666); +// printf("shmid :: %d\n", shmid); + +// if (shmid == -1) { +// printf("server not connected\n"); +// exit(1); +// } + +// if (shData == NULL) { +// printf("no running process\n"); +// exit(1); +// } + + // declare struct pointer + shData = (struct SharedData*)shmaddr; + + if(shData == NULL) { + printf("### shData NULL. no running process ###\n"); + exit(1); + } + + // server process + if (shData->pid != 0) { + printf("### [ %d ] server process running ###\n", shData->pid); + + int i = 0; + for (i = 0; i < MAX_USER_CNT; i++) { + if (shData->client[i].pid != 0) { + printf("### user [ %s ] running ###\n", shData->client[i].name); + } + } + } + + exit(1); + } + + // 2. server + if (strcmp(argv[2], "server") == 0) { + if (strcmp(argv[1], "start") == 0) { + // check shared memory +// shmid = shmget((key_t)0301, sizeof(shData), IPC_EXCL); +// printf("shmid :: %d\n", shmid); +// if (shmid != -1) { + // one server running ok +// printf("server running\n"); +// exit(1); +// } + // fork set + pid = fork(); + if (pid == -1) { + printf("### fork fail ###\n"); + } else if (pid == 0) { + // parent : new pid, child : return 0 + execl("./server", "start", (char*)0); + } + } + + else if (strcmp(argv[1], "stop") == 0) { +// shmid = shmget((key_t)0301, sizeof(shData), IPC_EXCL); +// if (shmid == -1) { +// printf("no running server\n"); +// exit(1); +// } + +// if ((shmaddr = shmat(shmid, (void*)0, 0)) == (void*)-1) { +// printf("shmat fail\n"); +// exit(1); +// } + + shData = (struct SharedData*)shmaddr; + if(shmid != -1) { + printf("### no running server stop start ###\n"); + exit(1); + } + + kill(shData->pid, SIGINT); + printf("### running server stop ###\n"); + } + else { + printf("### wrong keyword ###\n"); + } + } + + // 3. client + if (strcmp(argv[2], "client") == 0) { + shmid = shmget((key_t)0301, sizeof(shData), IPC_EXCL); + if (shmid == -1) { + printf("### shmget fail ###\n"); + exit(1); + } + + if ((shmaddr = shmat(shmid, (void*)0, 0)) == (void*)-1) { + printf("### shmat fail ###\n"); + exit(1); + } + + shData = (struct SharedData*)shmaddr; + + if (strcmp(argv[1], "stop") == 0) { + int i = 0; + for (i = 0; i < MAX_USER_CNT; i++) { + if (strcmp(argv[3], shData->client[i].name) == 0) { + kill(shData->client[i].pid, SIGINT); + printf("### user [ %s ] stop by control ###\n", argv[3]); + } + } + } + } + + return 0; +} + + +void connShMemory() { + shmid = shmget((key_t)0301, sizeof(shData), IPC_EXCL | IPC_CREAT | 0666); + printf("connShMemory shmid :: %d\n", shmid); + + if (shmid == -1) { + // shared memory check -> create, conn + shmid = shmget((key_t)0301, sizeof(shData), IPC_CREAT | 0666); + if(shmid == -1) { + printf("### shmget fail ###\n"); + + // shared memory separate / disconn + if(shmdt(shmaddr) == -1) { + printf("### shmdt fail ###\n"); + exit(1); + } + } else { + // shared memory allocate / conn + shmaddr = shmat(shmid, (void*)0, 0); + if(shmaddr == (void*)-1) { + printf("### shmat fail ###\n"); + exit(1); + } + } + } else { + // shared memory delete + if(shmctl(shmid, IPC_RMID, 0) == -1) { + printf("### shmctl fail ###\n"); + exit(1); + } + } +} diff --git a/simpleChatting/server.c b/simpleChatting/server.c new file mode 100755 index 0000000000000000000000000000000000000000..5a3034ed0cb7cb3df8d67ac6482e6027cf011379 --- /dev/null +++ b/simpleChatting/server.c @@ -0,0 +1,154 @@ +#include "comn.h" + +void UserConnServer(); // user connect to server +void UserDisConnServer(); // user disconnect to server +void MatchUserChat(); // users matching chat +void ServerStop(); // server stop + +void setSignal(); + +int main(int argc, char* argv[]) { + printf("\n [ server process ]\n"); + // regist signal(user conn, user disconn, server stop, chat) + setSignal(); + if (strcmp(argv[0], "start") == 0) { + shmid = shmget((key_t)0301, sizeof(shData), IPC_CREAT | 0666); + printf("shmid :: %d\n", shmid); + if (shmid == -1) { + printf("### shmget fail ###\n"); + exit(1); + } + + shmaddr = shmat(shmid, (void*)0, 0); + if (shmaddr == (void*)-1) { + printf("### shmat fail ###\n"); + exit(1); + } + + shData = (struct SharedData*)shmaddr; + + shData->pid = getpid(); + + if(shData == NULL) { + printf("### start server. shData NULL ###\n"); + } + + int i = 0; + for (i = 0; i < MAX_USER_CNT; i++) { + shData->client[i].pid = 0; + memset(shData->client[i].name, 0, sizeof(shData->client[i].name)); + } + + printf("========================\n"); + printf("\tServer Start\n"); + printf("========================\n"); + + while (1) { + while (1) { + if (info.shm_nattch == 3) { + break; + } + + if (shmctl(shmid, IPC_STAT, &info) == -1) { + printf("### shmctl fail ###"); + exit(1); + } + + sleep(1); + } + + MatchUserChat(); + + while (1) { + if (shmctl(shmid, IPC_STAT, &info) == -1) { + printf("### shmctl fail ###"); + exit(1); + } + + // waiting + if (info.shm_nattch < 3) { + break; + } + + sleep(1); + } + } + + } + return 0; +} + +void UserConnServer() { + printf("\n==================================\n"); + if (shData->client[1].pid != 0) { + printf("Connect Success : %s [%d]\n", shData->client[1].name, shData->client[1].pid); + } + else { + printf("Connect Success : %s [%d]\n", shData->client[0].name, shData->client[0].pid); + } + printf("==================================\n"); +} + +void MatchUserChat() { + kill(shData->client[0].pid, SIGUSR1); + printf("%d %d \n", strlen(shData->client[0].name), strlen(shData->client[1].name)); + printf("%s %s chatting match\n", shData->client[0].name, shData->client[1].name); + printf("==================================\n"); +} + +void UserDisConnServer() { + int i = 0; + for (i = 0; i < MAX_USER_CNT; i++) { + if (shData->client[i].pid == -1) { + printf("DisConnect : %s\n", shData->client[i].name); + shData->client[i].pid = 0; + memset(shData->client[i].name, 0, sizeof(shData->client[i].name)); + + } + } +} + +void ServerStop() { + + int i = 0; + for (i = 0; i < MAX_USER_CNT; i++) { + if (shData->client[i].pid != 0) { + kill(shData->client[i].pid, SIGINT); + } + } + + if (shmdt(shmaddr) == -1) { + printf("shmdt fail\n"); + exit(1); + } + if (shmctl(shmid, IPC_RMID, 0) == -1) { + printf("shmctl fail\n"); + exit(1); + } + + printf("========================\n"); + printf("\tServer Stop\n"); + printf("========================\n"); + exit(1); +} + +void setSignal() { + struct sigaction conn_sign; + struct sigaction disconn_sign; + struct sigaction server_stop_sign; + + conn_sign.sa_handler = UserConnServer; + sigemptyset(&conn_sign.sa_mask); + conn_sign.sa_flags = 0; + sigaction(SIGUSR1, &conn_sign, NULL); + + disconn_sign.sa_handler = UserDisConnServer; + sigemptyset(&disconn_sign.sa_mask); + disconn_sign.sa_flags = 0; + sigaction(SIGALRM, &disconn_sign, NULL); + + server_stop_sign.sa_handler = ServerStop; + sigemptyset(&server_stop_sign.sa_mask); + server_stop_sign.sa_flags = 0; + sigaction(SIGINT, &server_stop_sign, NULL); +}