U E D R , A S I H C RSS

권영기/채팅프로그램 (rev. 1.12)

권영기/채팅프로그램

Describe 권영기/채팅프로그램 here

2012/3/30 - 일대일 채팅 프로그램 만들기
2012/4/3 - 멀티채팅 프로그램 만들기

2012/3/30 - 일대일 채팅 프로그램 만들기


설명


서버에서도 메세지를 보낼 수 있고, 클라이언트에서도 메세지를 보낼 수 있습니다.
exit를 치면 채팅을 종료합니다.

문제점


exit를 쳤을 때, 종료가 제대로 되지 않는 것이 문제입니다.
client에서 exit를 쳤을 때, "채팅이 종료되었습니다." 라는 메세지가 바로 뜨지 않습니다. server에서 아무거나 입력하면 그제서야 client에서 "채팅이 종료되었습니다."가 출력됩니다.
그리고나서 server는 채팅 종료직전에 받았던 메세지를 무한히 출력합니다.
server에서 exit를 쳤을 때, "채팅이 종료되었습니다." 라는 메세지가 바로 뜨지 않습니다. client에서 아무거나 입력하면 그제서야 server에서 "채팅이 종료되었습니다."가 출력됩니다.
그리고나서 client는 채팅 종료직전에 받았던 메세지를 무한히 출력합니다.

무한 루프에 관한 문제는 해결되었습니다. - 2012. 4. 3



서버

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<pthread.h>
#define SIZE 1024
int client_socket, server_socket;
int client_addr_size, flag = 0;	
char buff_snd[SIZE + 5], buff_rcv[SIZE + 5];
void* snd(void *data){

	while(!flag){
		gets(buff_rcv);
		if(strcmp(buff_rcv, "exit") == 0)flag = 1;
		else{
			sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);
			send(client_socket, buff_snd, strlen(buff_snd)+1, 0);
		}
	}

}
void *rcv(void *data){
	int temp;
	while(!flag){
		if(recv(client_socket, buff_rcv, SIZE, 0) <= 0)continue;
		else{
			if(strcmp(buff_rcv, "exit") == 0)flag = 1;
			else{
				printf( "receive: %s\n", buff_rcv);
		      		sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);
			}
		}
	}
}
int main(void){
	
	int option = 1;
	pthread_t pthread[2];
	struct sockaddr_in server_addr, client_addr;
	


	

	server_socket = socket(PF_INET, SOCK_STREAM, 0);
	setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
	if (-1 == server_socket)
	{
	   printf( "server socket 생성 실패");
	   exit( 1) ;
	}

	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(4000);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);


	if(bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr))){

		printf( "bind() 실행 에러\n");
		exit( 1);
	}

	if(listen(server_socket, 5) == -1){
		printf( "대기상태 모드 설정 실패\n");
		exit( 1);
	} 

	client_addr_size = sizeof(client_addr);
	client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_size);
	if(client_socket == -1){
		printf( "클라이언트 연결 수락 실패\n");
 		exit(1);
	}

	pthread_create(&pthread[0], NULL, snd, (void *)NULL);
	pthread_create(&pthread[1], NULL, rcv, (void *)NULL);


	int status;
	pthread_join(pthread[0], (void**)&status);
	pthread_join(pthread[1], (void**)&status);

	printf("채팅이 종료되었습니다.\n");
	close(server_socket);
	return 0;
}

클라이언트

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#define  SIZE   1024
int flag = 0;
char buff_snd[SIZE + 5], buff_rcv[SIZE + 5];
int   client_socket;
void* snd(void *data){

	while(!flag){
		gets(buff_rcv);
		if(strcmp(buff_rcv, "exit") == 0)flag = 1;
		else{
			sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);
			send(client_socket, buff_snd, strlen(buff_snd)+1, 0);
		}
	}
}
void *rcv(void *data){

	int temp;
	while(!flag){
		if(recv(client_socket, buff_rcv, SIZE, 0) <= 0)continue;
		else{
			if(strcmp(buff_rcv, "exit") == 0)flag = 1;
			else{
				printf( "receive: %s\n", buff_rcv);
	      			sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);
			}	
		}
	}
}
int   main( int argc, char **argv)
{

	pthread_t pthread[2];

	struct sockaddr_in   server_addr;

	client_socket  = socket( PF_INET, SOCK_STREAM, 0);
	if( -1 == client_socket)
	{
		printf( "socket 생성 실패\n");
		exit( 1);
	}

	memset( &server_addr, 0, sizeof( server_addr));
	server_addr.sin_family     = AF_INET;	
	server_addr.sin_port       = htons( 4000);
	server_addr.sin_addr.s_addr= inet_addr( "127.0.0.1");

	if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
	{
		printf( "접속 실패\n");
		exit( 1);
	}

	pthread_create(&pthread[0], NULL, snd, (void *)NULL);
	pthread_create(&pthread[1], NULL, rcv, (void *)NULL);


	int status;
	pthread_join(pthread[0], (void**)&status);
	pthread_join(pthread[1], (void**)&status);
	printf("채팅이 종료되었습니다.\n");
	close(client_socket);
	return 0;
}


2012/4/3 - 멀티채팅 프로그램 만들기


설명


멀티 채팅이 됩니다.
이전에 작성했던 일대일 채팅 프로그램의 소스는 구조적으로 문제가 많았기 때문에 많은 수정이 필요했습니다.
이제 멀티채팅을 완성했는데, 희성이는 계정이 적용된 채팅을 만들었군요.. 멘붕

의문점


프로그램을 작성하면서 들었던 의문점은 Pthread_join에 관한 것입니다. 서버쪽에서 쓰레드를 쓰면서 Join을 어디다가 놔야할지를 모르겠어서 한번 빼놓고 해보니까 프로그램이 잘 작동이 되었습니다.(우연의 산물 ㅠㅠ)
하지만 join이 없으면 자원이 해제가 되지 않으니 메모리 누수가 생길 겁니다. 그래서 저는 join을 사용하고 싶은데 어떻게 해야할 지를 모르겠네요.

문제점


소스가 정리가 안되서 지저분합니다.

서버


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<pthread.h>
#define SIZE 1024
#define N 40
int client_socket[N+5], check[N+5], server_socket;
int client_addr_size, flag = 0;	
char buff_snd[SIZE + 5], buff_rcv[SIZE + 5];
void *rcv(void *data){
	int i;
	int temp = (int *)data;
	while(1){
		if(recv(client_socket[temp], buff_rcv, SIZE, 0) <= 0)continue;
		else{
			if(strcmp(buff_rcv, "exit") == 0){
				printf("채팅이 종료되었습니다.\n");
				break;
			}
			printf( "receive: %s\n", buff_rcv);
		      	sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);
			for(i = 1; i<=N; i++){
				if(check[i])send(client_socket[i], buff_snd, strlen(buff_snd)+1, 0);
			}
		}
	}

	close(client_socket[temp]);
	client_socket[temp] = check[temp] = 0;
}
int main(void){
	
	int option = 1;
	pthread_t pthread[N+5];
	struct sockaddr_in server_addr, client_addr;
	int i;


	

	server_socket = socket(PF_INET, SOCK_STREAM, 0);
	setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
	if (-1 == server_socket)
	{
	   printf( "server socket 생성 실패");
	   exit( 1) ;
	}

	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(4000);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);


	if(bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr))){

		printf( "bind() 실행 에러\n");
		exit( 1);
	}

	while(1){
		if(listen(server_socket, 5) == -1){
			printf( "대기상태 모드 설정 실패\n");
			exit( 1);
		} 
		for(i = 1; i<=N; i++){
			
			if(!check[i]){
				client_addr_size = sizeof(client_addr);
				client_socket[i] = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_size);
				if(client_socket[i] == -1){
					printf( "클라이언트 연결 수락 실패\n");
		 			exit( 1);
				}
				check[i] = 1;
				pthread_create(&pthread[i], NULL, rcv, (void *)i);


				//int status;
				//pthread_join(pthread[i], (void **)&status);
				break;
			}
		}

	}

	printf("채팅이 종료되었습니다.\n");
	close(server_socket);
	exit(1);
	return 0;
}


클라이언트



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#define  SIZE   1024
int flag1 = 0, flag2 = 0;
char buff_snd[SIZE + 5], buff_rcv[SIZE + 5];
int   client_socket;
void* snd(void *data){

	while(!flag1){
		while(flag2);
		gets(buff_rcv);	
		send(client_socket, buff_rcv, strlen(buff_rcv)+1, 0);
		if(strcmp(buff_rcv, "exit") == 0){
			flag1 = 1;
			printf("채팅이 종료되었습니다.\n");	
			pthread_exit((void *)NULL);
		}
		flag2 = 1;
	}
}
void *rcv(void *data){

	int temp;
	while(!flag1){
		if(recv(client_socket, buff_rcv, SIZE, 0) <= 0)continue;
		else{
			printf( "receive: %s\n", buff_rcv);
      			sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);
			flag2 = 0;
		}
	}
}
int   main( int argc, char **argv)
{

	pthread_t pthread[2];

	struct sockaddr_in   server_addr;

	client_socket  = socket( PF_INET, SOCK_STREAM, 0);
	if( -1 == client_socket)
	{
		printf( "socket 생성 실패\n");
		exit( 1);
	}

	memset( &server_addr, 0, sizeof( server_addr));
	server_addr.sin_family     = AF_INET;	
	server_addr.sin_port       = htons( 4000);
	server_addr.sin_addr.s_addr= inet_addr( "127.0.0.1");

	if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
	{
		printf( "접속 실패\n");
		exit( 1);
	}

	pthread_create(&pthread[0], NULL, snd, (void *)NULL);
	pthread_create(&pthread[1], NULL, rcv, (void *)NULL);


	int status;
	pthread_join(pthread[0], (void**)&status);
	pthread_join(pthread[1], (void**)&status);
	close(client_socket);
	exit(1);
	return 0;
}

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:28:46
Processing time 0.0373 sec