티스토리 뷰
Study/네트워크 실습
다중접속 채팅프로그램 및 Flag를 이용한 1. 실시간 채팅 (닉네임 변경 가능) 2. 더치 페이 기능 (계산기 활용) 3. 미니 게임 기능 (가위바위보 활용) 4. 파일 공유 기능 (파일 전송 활용)
15051015 2019. 12. 17. 21:07최대 100명까지 접속 가능한 서버와 서버를 통해 실시간 채팅은 유지하면서 다양한 기능을 사용하는 프로그램입니다. 최대한 실시간 채팅 기능을 유지하는 방향으로 만들었습니다. Flag 를 통해 더 많은 기능을 확장 할 수 있는 채팅 프로그램입니다.
구현된 기능 목록
1. 실시간 채팅 (닉네임 변경 가능)
2. 더치 페이 기능 (계산기 활용)
3. 미니 게임 기능 (가위바위보 활용)
4. 파일 공유 기능 (파일 전송 활용)
다중 접속 쓰레드 및 채팅은 아래의 블로그를 참고로 만들었습니다.
https://good-coding.tistory.com/17




#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<pthread.h>
#include<time.h>
#define BUF_SIZE 100
#define MAX_CLNT 100 //max socket comunication 100
#define MAX_IP 30
void * handle_clnt(void *arg);
void send_msg(char *msg, int len);
void error_handling(char *msg);
char* serverState(int count);
void menu(char port[]);
char msgpay[BUF_SIZE];
int flagz=0;
//volatile int gameflag=0;
/****************************/
int clnt_cnt=0;//how much clnt ?
int clnt_socks[MAX_CLNT]; // max join 100, socket [100]
pthread_mutex_t mutx;
int main(int argc, char *argv[])
{
int serv_sock, clnt_sock;
struct sockaddr_in serv_adr, clnt_adr;
int clnt_adr_sz;
pthread_t t_id;
//socket create, and thread ready
/** time log **/
struct tm *t;
time_t timer = time(NULL);
t=localtime(&timer);
if (argc != 2)
{
printf(" Usage : %s <port>\n", argv[0]);
exit(1);
}
//port input please
menu(argv[1]);
//information
pthread_mutex_init(&mutx, NULL);
serv_sock=socket(PF_INET, SOCK_STREAM, 0);
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_adr.sin_port=htons(atoi(argv[1]));
//in serv_sock
if (bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
error_handling("bind() error");
if (listen(serv_sock, 5)==-1)
error_handling("listen() error");
//error check
while(1)
{//loop accept
t=localtime(&timer);
clnt_adr_sz=sizeof(clnt_adr);
clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
pthread_mutex_lock(&mutx);
clnt_socks[clnt_cnt++]=clnt_sock;//new client join macthing clnt_sock[]
pthread_mutex_unlock(&mutx);
pthread_create(&t_id, NULL, handle_clnt, (void*)&clnt_sock);//thread
pthread_detach(t_id);
printf(" Connceted client IP : %s ", inet_ntoa(clnt_adr.sin_addr));
printf("(%d-%d-%d %d:%d)\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday,
t->tm_hour, t->tm_min);//join time
printf(" chatter (%d/100)\n", clnt_cnt);
}
close(serv_sock);
return 0;
}
void *handle_clnt(void *arg) //in thread
{
int clnt_sock=*((int*)arg);
int str_len=0, i;
char msg[BUF_SIZE];
char filename[100];
FILE *fp;
char filebuf[100];
char name_cnt[2];
size_t bufsize = 0;
int nbyte;
memset(filebuf, 0x00,30);
char filesize[5];
int read_cnt;
char totalprice[100];
char howm[100];
int price =1;
int howmany =1;
int result=1;
char result_c[100];
int gamenum;
char gamec[100];
char temp[100];
char flag[2];
char gamemsg[20];
int win,won;
char under[2];
char up[2];
char please[2];
won = (rand() %1000) +1;
while(1)
{//caculater ++ function
read(clnt_sock,flag,1);
if(strcmp(flag,"`")==0)//ducth pay
{
read(clnt_sock, howm, 2);//People
howmany = atoi(howm);
read(clnt_sock, totalprice, 10);//Total Price
price = atoi(totalprice);
strcpy(msg," people : ");
strcat(msg,howm);
strcat(msg,", totalprice : ");//msg add information
strcat(msg,totalprice);
strcat(msg," won , Per person: ");
result = price/howmany; // caculate
sprintf(result_c,"%d",result);
strcat(msg,result_c);//msg add result
strcat(msg," won -");
str_len=strlen(msg);
}
else if (strcmp(flag,")")==0)
{
sprintf(under,"%d",1);
sprintf(up,"%d",2);
sprintf(please,"%d",3);
while(strcmp(flag,")")==0)
{
int aa=0;
int cc=0;
read(clnt_sock,gamec,4);
win=atoi(gamec);
// strcpy(msg,gamec);
str_len=strlen(msg);
if(won==win)
{
//strcpy(msg, "Clear! minigame Winner is -> ");
// gameflag=0;
write(clnt_sock,")",1);
break;
}
else if(win>won)
{
write(clnt_sock,under,2);
}
else if(win<won)
{ write(clnt_sock,up,2);
}
else
{
write(clnt_sock,please,2);
}
}
memset(msg,0,sizeof(msg));
}
else if (strcmp(flag,"_")==0)
{
memset(msg,0,sizeof(msg));
read(clnt_sock, name_cnt,2);
read(clnt_sock, filename, atoi(name_cnt));//filename read
fp=fopen(filename,"wb");
read(clnt_sock,filesize,5); //file size read
int asize = atoi(filesize);
read_cnt=read(clnt_sock,filebuf,asize);//file read
fwrite((void*)filebuf, 1, read_cnt, fp);//file fwrite
strcpy(msg,filesize);
strcpy(msg,filename);
strcat(msg," stored :\n");
strcat(msg,filebuf);
str_len=strlen(msg);
fclose(fp);
}
else if (strcmp(flag,"}")==0)
{
int ifsize = 0;
char fsize[5];
memset(msg,0,sizeof(msg));
read(clnt_sock, name_cnt,2);
read(clnt_sock, filename, atoi(name_cnt));//filename read
//good
fp=fopen(filename,"rb");//file open
fseek(fp, 0, SEEK_END);
ifsize = ftell(fp);//fsize == filesize
fseek(fp, 0, SEEK_SET);
sprintf(fsize,"%d",ifsize);
write(clnt_sock,fsize,5);//file size write good
if(fp!=NULL)
{//fail
read_cnt=fread((void*)filebuf,1,ifsize,fp);//file read
}
usleep(500000);
strcpy(msg,filebuf);//go msg, filebuf
fclose(fp);
}
else
{
str_len=read(clnt_sock, msg, sizeof(msg));
//30000===================================================
if(str_len==0)
{break;}
}
send_msg(msg, str_len);//read and write all clnt_cnt[]
}
// remove disconnected client
pthread_mutex_lock(&mutx);
for (i=0; i<clnt_cnt; i++)
{
if (clnt_sock==clnt_socks[i])
{
while(i++<clnt_cnt-1)
clnt_socks[i]=clnt_socks[i+1];
break;
}
}
clnt_cnt--;
pthread_mutex_unlock(&mutx);
close(clnt_sock);
return NULL;
}
void send_msg(char* msg, int len)
{
int i;
pthread_mutex_lock(&mutx);
for (i=0; i<clnt_cnt; i++)//all clnt
write(clnt_socks[i], msg, len);
pthread_mutex_unlock(&mutx);
}
void error_handling(char *msg)
{
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}
char* serverState(int count)
{
char* stateMsg = malloc(sizeof(char) * 20);
strcpy(stateMsg ,"None");
if (count < 5)
strcpy(stateMsg, "Good");
else
strcpy(stateMsg, "Bad");
return stateMsg;
}
void menu(char port[])
{
system("clear");
printf(" **** moon/sun chat server ****\n");
printf(" server port : %s\n", port);
printf(" server state : %s\n", serverState(clnt_cnt));
printf(" max connection : %d\n", MAX_CLNT);
printf(" **** Log ****\n\n");
}
/** chat_client **/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<pthread.h>
#include<time.h>
#define BUF_SIZE 100
#define NORMAL_SIZE 20
void* send_msg(void* arg);
void* recv_msg(void* arg);
void error_handling(char* msg);
void menu();
void changeName();
void menuOptions(int sock);
void dutchpay();
void minigame();
void filetransfer(int sock);
void filedownload(int sock);
void filenamewrite(int sock);
char filename[30];
char name[NORMAL_SIZE]="[DEFALT]"; // name
char msg_form[NORMAL_SIZE]; // msg form
char serv_time[NORMAL_SIZE]; // server time
char msg[BUF_SIZE]; // msg
char serv_port[NORMAL_SIZE]; // server port number
char clnt_ip[NORMAL_SIZE]; // client ip address
volatile int flagz=0;
volatile int flagzz=0;
volatile int gameflag=0;
char team[2];
pthread_mutex_t mutx;
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in serv_addr;
pthread_t snd_thread, rcv_thread;
void* thread_return;
int result,total,person;
if (argc!=4)
{
printf(" Usage : %s <ip> <port> <name>\n", argv[0]);
exit(1);
}
/** local time **/
struct tm *t;
time_t timer = time(NULL);
t=localtime(&timer);
sprintf(serv_time, "%d-%d-%d %d:%d", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour,
t->tm_min);
sprintf(name, " [%s] -", argv[3]);
sprintf(clnt_ip, "%s", argv[1]);
sprintf(serv_port, "%s", argv[2]);
sock=socket(PF_INET, SOCK_STREAM, 0);
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
serv_addr.sin_port=htons(atoi(argv[2]));
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
error_handling(" conncet() error");
// call menu
menu();
//send, recvS separate
pthread_create(&snd_thread, NULL, send_msg, (void*)&sock);
pthread_create(&rcv_thread, NULL, recv_msg, (void*)&sock);
pthread_join(snd_thread, &thread_return);
pthread_join(rcv_thread, &thread_return);
close(sock);
return 0;
}
void* send_msg(void* arg)
{
int sock=*((int*)arg);
char name_msg[NORMAL_SIZE+BUF_SIZE];
char myInfo[BUF_SIZE];
char* who = NULL;
char temp[BUF_SIZE];
int price;
char totalprice[100];
int howmany;
char howm[100];
int gamenum;
char gamec[100];
char under[]="under\n";
char up[] ="up\n";
char please[] = "please number\n";
int k=0;
/** send join messge **/
printf(" >> join the chat !! \n");
sprintf(myInfo, "%s's join. IP_%s\n",name , clnt_ip);
write(sock, myInfo, strlen(myInfo));
while(1)
{
fgets(msg, BUF_SIZE, stdin);
// menu_mode command -> !menu
if (!strcmp(msg, "!menu\n"))
{//input menu -> can select
menuOptions(sock);
}
if(flagz==1)//ducth pay
{
strcpy(msg,"`");//function use flag
write(sock, msg, 1);
printf("Input How many? : ");
scanf("%d",&howmany);
sprintf(howm,"%d",howmany);
write(sock, howm, 2);//People
printf("Input total price : ");
scanf("%d",&price);
sprintf(totalprice,"%d",price);
write(sock, totalprice, 10);//Total Price
flagz=0;
memset(msg,0,sizeof(msg));
continue;
}
else if (flagz==2)
{
while(flagz==2)//minigame
{//int i;
strcpy(msg,")");
write(sock, msg, 1);
memset(msg,0,sizeof(msg));
printf("\n Guess number!! choose between 1~999 (second line is fake) : \n");
scanf("%d",&gamenum);
//printf(" Enter Please \n");
sprintf(gamec,"%d",gamenum);
write(sock, gamec,4);
}
flagz=0;
memset(msg,0,sizeof(msg));
continue;//dkfo write tlfgodgkwl dksgrldnlgo
}
else if (flagz==3)
{
memset(name_msg,0,sizeof(name_msg));
filetransfer(sock);
// memset(name_msg,0,sizeof(name_msg));
flagz=0;
continue;
}
else if (flagz==4)
{
memset(name_msg,0,sizeof(name_msg));
filenamewrite(sock);
flagzz=9;
flagz=0;
usleep(1000000);
continue;
}
else if (!strcmp(msg, "q\n") || !strcmp(msg, "Q\n"))
{
close(sock);
exit(0);
}
// send message qq, 2002
sprintf(name_msg, "%s %s", name,msg);
write(sock, name_msg, strlen(name_msg));//2
}
return NULL;
}
void* recv_msg(void* arg)
{
int sock=*((int*)arg);
char name_msg[NORMAL_SIZE+BUF_SIZE];
int str_len;
char flg[2];
char temp[3];
int a;
while(1)
{
if(flagz==2)
{
read(sock,flg,1);
a=atoi(flg);
if(a==1)
{
printf("down.. \n ",flg);
}
else if(a==2)
{
printf("up \n ",flg);
}
else if(a==3)
{
printf("error, retry \n");
}
else if(strcmp(flg,")")==0)
{ printf("Congratulations! You are Winner! \n");
memset(name_msg,0,sizeof(name_msg));
flagz=0;
}
}
else if(flagz==4 || flagzz==9 )
{
FILE *fp;
char filebuf[100];
memset(filebuf, 0x00,100);
int read_cnt;
char filesize[5];
int ifsize = 0;
strcpy(filesize,name_msg);//read name_msg, filesize
fp=fopen(filename,"wb");
ifsize = atoi(filesize);
memset(name_msg,0,sizeof(name_msg));//name_msg = 0
usleep(400000);
read_cnt=read(sock,filebuf,ifsize);//file read
fwrite((void*)filebuf, 1, read_cnt, fp);//file fwrite
printf(" %s is stored!! ",filename);
fclose(fp);
flagz=0;
flagzz=0;
}
str_len=read(sock, name_msg, NORMAL_SIZE+BUF_SIZE-1);
if (str_len==-1)
return (void*)-1;
name_msg[str_len]=0;
fputs(name_msg, stdout);
}
return NULL;
}//flagz=2;
void menuOptions(int sock)
{
int select;
// print menu
printf("\n\t**** menu mode ****\n");
printf("\t1. change name\n");
printf("\t2. clear/update\n\n");
printf("\t3. dutchpay\n\n");
printf("\t4. minigame\n\n");
printf("\t5. file transfer\n\n");
printf("\t6. file download\n\n");
printf("\tthe other key is cancel");
printf("\n\t*******************");
printf("\n\t>> ");
scanf("%d", &select);
getchar();
switch(select)
{
// change user name
case 1:
changeName();flagz=0;
break;
// console update(time, clear chatting log)
case 2:
menu();flagz=0;
break;
case 3:
printf("dutchpay funtion start\n");
flagz=1;
break;
case 4:
printf("minigame funtion start\n");
flagz=2;
break;
case 5:
printf("filetransfer funtion start\n");
flagz=3;
break;
case 6:
printf("filedownload funtion start\n");
flagz=4;
break;
// menu error
default:
printf("\tcancel.");flagz=0;
break;
}
}
void dutchpay()
{
/*
int price;
char totalprice[100];
int howmany;
char howm[100];
strcpy(msg,"!price");
write(sock, msg, strlen(msg));
printf("Input total price : ");
scanf("%d",&price);
sprintf(totalprice,"%d",price);
write(sock, totalprice, strlen(totalprice));
printf("Input How may? : ");
scanf("%d",&howmany);
sprintf(howm,"%d",howmany);
write(sock, howm, strlen(howm));
*/
}
void minigame()
{
}
void filetransfer(int sock)
{
int i = 0;
FILE *fp;
char filebuf[256];
int read_cnt;
char name_cnt[2];
int ifsize = 0;
char fsize[5];
//memset(filebuf, 0x00, 256);
strcpy(msg,"_");
write(sock, msg, 1);//flag write
printf("Input filename :");
fgets(filename, 20, stdin);
for(i = 0 ; filename[i] !=0; i++)
{// if ==\n
if(filename[i] == '\n') {
filename[i] = 0;
break;
}
}
sprintf(name_cnt,"%d",strlen(filename));
write(sock,name_cnt,2);//filename length
write(sock,filename,(strlen(filename))); // filename notice
fp=fopen(filename,"rb");
fseek(fp, 0, SEEK_END);
ifsize = ftell(fp);//fsize == filesize
fseek(fp, 0, SEEK_SET);
sprintf(fsize,"%d",ifsize);
write(sock,fsize,5);
if(fp!=NULL)
{
while(1)
{
read_cnt=fread((void*)filebuf,1,ifsize,fp);
if(read_cnt<ifsize)
{
write(sock,filebuf,read_cnt);
break;
}
write(sock,filebuf,read_cnt);
}
}
flagz=0;
fclose(fp);
}
void filedownload(int sock)
{
/*
int i = 0;
FILE *fp;
char filebuf[100];
memset(filebuf, 0x00,30);
int read_cnt;
char name_cnt[2];
char filesize[5];
int ifsize = 0;
char fsize[5];
char temp[10];
//memset(filebuf, 0x00, 256);
read(sock,filesize,5); //file size read
fp=fopen(filename,"wb");
// pthread_mutex_lock(&mutx);
ifsize = atoi(filesize);
//printf("\n%s\n",filesize);//size rhdqor;
printf("\n%s\n",filename);
printf("\n%s\n",filebuf);
printf("\n%d\n",ifsize);
read_cnt=read(sock,filebuf,ifsize);//file read
fwrite((void*)filebuf, 1, read_cnt, fp);//file fwrite
// pthread_mutex_unlock(&mutx);
fclose(fp);
*/
}
void filenamewrite(int sock)
{
int i = 0;
FILE *fp;
char filebuf[256];
int read_cnt;
char name_cnt[2];
char filesize[5];
int ifsize = 0;
char fsize[5];
//memset(filebuf, 0x00, 256);
strcpy(msg,"}");
write(sock, msg, 1);//flag write
printf("Input filename :");
fgets(filename, 20, stdin);
for(i = 0 ; filename[i] !=0; i++)
{// if ==\n
if(filename[i] == '\n') {
filename[i] = 0;
break;
}
}
sprintf(name_cnt,"%d",strlen(filename));
write(sock,name_cnt,2);//filename length
write(sock,filename,(strlen(filename))); // filename notice
}
/** change user name **/
void changeName()
{
char nameTemp[100];
printf("\n\tInput new name -> ");
scanf("%s", nameTemp);
strcpy(msg,name);
strcat(msg," --> change name! --> ");
sprintf(name, " [%s] -", nameTemp);
printf("\n\tComplete.\n\n");
}
void menu()
{
system("clear");
printf(" **** moon/sum chatting client ****\n");
printf(" server port : %s \n", serv_port);
printf(" client IP : %s \n", clnt_ip);
printf(" chat name : %s \n", name);
printf(" server time : %s \n", serv_time);
printf(" ************* menu ***************\n");
printf(" if you want to select menu -> !menu\n");
printf(" 1. change name\n");
printf(" 2. clear/update\n");
printf(" **********************************\n");
printf(" Exit -> q & Q\n\n");
}
void error_handling(char* msg)
{
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}
'Study > 네트워크 실습' 카테고리의 다른 글
소켓프로그래밍 in c (Linux 환경) 코드분석과 흐름 2 (0) | 2019.11.28 |
---|---|
소켓프로그래밍 in c (Linux 환경) 코드분석과 흐름 1 (1) | 2019.11.14 |
패킷트레이서 실습 3-3 (0) | 2019.10.10 |
패킷트레이서 - WAN 환경 구축 (3) | 2019.09.26 |
패킷트레이서 실습 1 (0) | 2019.09.05 |