티스토리 뷰

최대 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);
}

 

 

 

 

댓글
최근에 올라온 글
최근에 달린 댓글
250x250