채팅서버 fifo방식 문제...

zzzalxl의 이미지

채팅서버를 fifo방식을 써서 구현했는데 서버창하나 클라이언트창 두개로해서

각 클라이언트끼리 채팅을 주고받는 것을 구현해서 성공했습니다.

근데 한쪽은 주고 한쪽은 받고만 하는거라 이 방식을 양쪽다 주고받고를 동시에

실시간으루 구현하려고 하는데 도무지 감이 안잡혀서요...

고수님들 답변 바랍니다.

/*
* echo_serv
* test
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <time.h>
#include <malloc.h>
#include <sys/ipc.h>
 
#include "echo_serv.h"
#define INITCHER(x) memset(x, 0x00, sizeof(x))
#define BUFSIZE 1024
#define FIFO_GET "fifo1"
#define FIFO_SEND "fifo2"
 
/*
#define _DEBUG_
*/
	EXEC SQL INCLUDE SQLCA;
void RemoveHeadTail(char *str);
void error(char *message);
void z_handler(int sig);
int echo_serv(int clnt_sock);
 
int main()
{
	int serv_sock;
	int clnt_sock;
	int str_len;
	pid_t pid;	
	struct sockaddr_in servaddr;
	struct sockaddr_in clntaddr;
	int clntlen;
	char buff[1000];
	struct sigaction act;
 		act.sa_handler = z_handler;
 		sigemptyset(&act.sa_mask);
 		act.sa_flags = 0;
 
	Connect_Olacle();
	demon_d();
 
	sigaction(SIGCHLD, &act, 0);
 
	serv_sock = socket(PF_INET, SOCK_STREAM,0);
	if(serv_sock==-1)
		error("socket() error");
 
	memset(&servaddr,0,sizeof(servaddr));
	servaddr.sin_family=AF_INET;
	servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
	servaddr.sin_port=htons(9990);
 
	if(bind(serv_sock,(struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
    	fprintf(stderr, "server: can't bind local address\n");
    	close(serv_sock);
		exit(-1);
    }
 
	if(listen(serv_sock,5)==-1){
		error("listen() error");
	}
	printf("채팅 접속 대기중\n");
 
	for(;;){
 
		clntlen = sizeof(clntaddr);
		clnt_sock=accept(serv_sock,(struct sockaddr*)&clntaddr,&clntlen);
		if(serv_sock == -1){
			error("accept() error");
		}
		/*
		if(str_len=read(clnt_sock,buff, sizeof(buff)) == 0){
			return(0);
		}*/
		fflush(stdout); 
		pid = fork();
		if (pid < 0){
			printf("fork error");
			close(clnt_sock);
			continue;
		}else if(pid == 0){
 
			close(serv_sock);
			echo_serv(clnt_sock);
			close(clnt_sock) ;
 
			return(0);
		}else{
			close(clnt_sock) ;
		}	
 
	}
	Commit_Olacle();
	close(clnt_sock);
	return(0);
}
 
int demon_d()
{
	pid_t pid;
 
	if((pid = fork()) < 0){ 
		return(-1);
	}else if(pid != 0){
        exit(0);
   	}   
	setsid();       
	umask(0);     
 
  return(0);
}
 
void error(char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}
 
void z_handler(int sig)
{
  pid_t pid;
  int rtn;
  pid=waitpid(-1, &rtn, WNOHANG);
}
 
int Connect_Olacle(void)
{
	EXEC SQL BEGIN DECLARE SECTION;
		char uname[20];
		char pw[20];
	EXEC SQL END DECLARE SECTION;
 
		INITCHER(uname);
		INITCHER(pw);
 
		strcpy(uname,"zipcode");
		strcpy(pw,"zipcode");
 
	EXEC SQL CONNECT :uname IDENTIFIED BY :pw; 
 
		if(sqlca.sqlcode != 0){
			printf(" DB 접속 에러!", sqlca.sqlcode);
			return(1);
		}else{
			printf("채팅DB접속\n");
		}
		return(0);
}
 
int Commit_Olacle(void)
{
	EXEC SQL COMMIT WORK RELEASE;
 
		printf("DB 접속 종료! 수고하셨습니다!\n");
		return(0);
}

int echo_serv(int clnt_sock)
{
	EXEC SQL BEGIN DECLARE SECTION;
		char *a,*b,*id,*p,*p2,*p3;
		typedef struct{
			char id[15];
			char id2[15];
			char pw[20];
			char flag[10];
			char message[BUFSIZE];
		}	ServStruct;
 
		ServStruct *arr1;
		ServStruct *arr2;
 
	EXEC SQL END DECLARE SECTION;
		time_t s_time;
		char ch[BUFSIZE];
		int str_len1,str_len2;
		int i,j;
		int cmp;
		int fd,fd1;
		char fff[10];
		char buff[1000];
		/*처음 로그인*/
		char *login = "1";
		/* 3회 오류 */	
		char *pw3 = "2";	
		/*신규 유저*/
		char *new_user = "3";
		/*암호 수정*/	
		char *pwchange = "4";
		/*로그인 상태*/	
		char *logon = "5";	
		char *logout = "6";
		int sss=0;
		typedef struct{
			long data_type;
			char to_id[15];
			char data_buff[100];
		}	t_data;
		int mspid;
		int ndx =0;
		t_data *data;
		int pipe_get[2];
		int pipe_send[2];
 
		data = (t_data*) malloc( sizeof(t_data));	
		arr1 = (ServStruct*) malloc( sizeof(ServStruct));	/*malloc 사용*/
		arr2 = (ServStruct*) malloc( sizeof(ServStruct));



while(str_len2=read(clnt_sock,buff, sizeof(buff)) != 0){ /*로그인 과정*/ /*플래그의 상태를 확인하여 최초 로그인, 3회 오류, 신규가입, 암호변경을 확인*/
memset(arr1, 0x00, sizeof(ServStruct));
memset(arr2, 0x00, sizeof(ServStruct));
printf("[%s]\n",buff);
p = strtok(buff,"|");
p2 = strtok(NULL,"|");
p3 = strtok(NULL,"|");
strcpy(arr2->id,p);
strcpy(arr2->pw,p2);
strcpy(arr2->flag,p3);
/*신규가입 플래그가 들어왔을시 DB에 신규 INSERT*/
if(!strcmp(arr2->flag,new_user)){
EXEC SQL SELECT I INTO :arr1->id
FROM LOG_DATA
WHERE I = :arr2->id;
EXEC SQL COMMIT;
RemoveHeadTail(arr1->id);
/*검색하여 기존에 있는 사용자인지 확인, 기존 유저가 있으면 플래그를 클라이언트로 보냄*/
if(!strcmp(arr1->id,arr2->id)){
printf("존재하는 아이디 입니다.\n");
strcpy(buff,"uu");
write(clnt_sock, buff, sizeof(buff));
}else{
EXEC SQL INSERT INTO LOG_DATA(I, P, F)
VALUES(:arr2->id, :arr2->pw, :arr2->flag);
EXEC SQL COMMIT;
strcpy(arr1->id,arr2->id);
break;
}
/* }else if(strcmp(arr2->flag,login)){
EXEC SQL SELECT I INTO :arr1->id
FROM LOG_DATA
WHERE I = :arr2->id; */
/*전회에 3회 오류시 플래그를 클라이언트로 보냄*/
}else if(!strcmp(arr2->flag,pw3)){
printf("pw 3번 오류\n");
EXEC SQL UPDATE LOG_DATA
SET F = :arr2->flag
WHERE I = :arr2->id;
EXEC SQL COMMIT;
/*암호 수정을 받는 부분*/
}else if(!strcmp(arr2->flag,pwchange)){
strcpy(arr2->flag,logon);
EXEC SQL UPDATE LOG_DATA
SET P =:arr2->pw, F =:arr2->flag
WHERE I =:arr2->id;
EXEC SQL COMMIT;
break;
}
/*클라이언트로 부터 아이디 암호를 받아서 유저 테이블을 검색*/
EXEC SQL SELECT I,P,F
INTO :arr1->id, :arr1->pw, :arr1->flag
FROM LOG_DATA
WHERE I = :arr2->id;
EXEC SQL COMMIT;
RemoveHeadTail(arr1->id);
RemoveHeadTail(arr1->pw);
RemoveHeadTail(arr1->flag);
printf("[%s]\n",arr1->id);
/*입력받은 아이디가 유저 테이블에 없을시 플래그를 클라이언트로 보냄*/
if(strcmp(arr1->id,arr2->id)){
printf("ID를 찾지 못했습니다.\n");
strcpy(buff,"i");
write(clnt_sock, buff, sizeof(buff));
memset(buff, 0x00, sizeof(buff));
/*입력받은 암호가 검색 결과와 다를시 플래그를 클라이언트로 보냄*/
}else if(strcmp(arr1->pw,arr2->pw)){
printf("암호가 틀렸습니다.\n");
strcpy(buff,"p");
write(clnt_sock, buff, sizeof(buff));
memset(buff, 0x00, sizeof(buff)) ;
/*검색한 플래그가 3회 오류 상태였을시 플래그 보냄*/
}else if(!strcmp(arr1->flag,pwchange)){
printf("전회 암호 3번 오류, 수정 요망\n");
strcpy(buff,"x");
write(clnt_sock, buff, sizeof(buff));
memset(buff, 0x00, sizeof(buff)) ;
}else{
strcpy(buff,"fff");
write(clnt_sock,arr1->message, str_len2);
break;
}
}
EXEC SQL UPDATE LOG_DATA
SET F = :arr2->flag
WHERE I = :arr1->id;
EXEC SQL COMMIT;

printf("접속완료...\n");
if(mkfifo(FIFO_GET, 0666)==-1){ /*fifo생성함수써서 생성*/
printf("wait....\n");
}
if((fd =open(FIFO_GET, O_RDWR))==-1){ /*오픈하고 파일 디스크립터를 리턴*/
printf("wait...\n");
}
read(clnt_sock,ch, sizeof(buff));
#ifdef _DEBUG_
printf("[%s]\n",buff);
#endif
while(1){
if(!strcmp(ch,"1")){
printf("[%s]님이 메세지 입력중...\n",arr2->id);
read(clnt_sock,buff, sizeof(buff));
p = strtok(buff,"|");
p2 = strtok(NULL,"|");
p3 = strtok(NULL,"|");
strcpy(arr2->id2,p);
strcpy(arr2->message,p2);
strcpy(arr2->flag,p3);
#ifdef _DEBUG_
printf("[%s],[%s],[%s]\n",arr2->id2,arr2->message,arr2->flag);
#endif
EXEC SQL SELECT I,F
INTO :arr1->id2,:arr1->flag
FROM LOG_DATA
WHERE I = :arr2->id2;
EXEC SQL COMMIT;
RemoveHeadTail(arr1->id2);
RemoveHeadTail(arr1->flag);
RemoveHeadTail(ctime(&s_time));
#ifdef _DEBUG_
printf("[%s],[%s]\n",arr1->id2,arr2->id2);
#endif
/* if(strcmp(arr1->id2,arr2->id2)){
printf("없는 ID입니다.\n");
memset(buff,0x00,sizeof(buff));
strcpy(arr2->flag,"NU");
sprintf(buff,"%s|%s|%s|",arr1->id,arr2->message,arr2->flag);
write(clnt_sock, buff, sizeof(buff));
}else if(strcmp(arr1->flag,login)){
printf("없는 user ID\n");
memset(buff,0x00,sizeof(buff));
strcpy(buff,"NU");
write(clnt_sock, buff, sizeof(buff));
}else{ */
memset(buff, 0x00, sizeof(buff)) ;
write(clnt_sock, buff, sizeof(buff));
time(&s_time);
printf("=======================\n");
printf("-수신ID :[%s]\n",arr2->id2);
printf("-요청시간 :[%s]\n",ctime(&s_time));
printf("-요청 메세지 : [%s]\n",arr2->message);
printf("=======================\n");

EXEC SQL INSERT INTO CHAT_DATA(I,I2,T,A)
VALUES(:arr1->id,:arr2->id2, SYSDATE, :arr2->message);
EXEC SQL COMMIT;
sprintf(buff,"%s|%s|%s|",arr1->id,arr2->message,arr2->id2);
#ifdef _DEBUG_
printf("송신[%s]\n",buff);
#endif
write(fd, buff, sizeof(buff));
#ifdef _DEBUG_
printf("송신 ID[%s]\n",arr1->id);
#endif
memset(buff, 0x00, sizeof(buff)) ;
strcpy(ch,"2");

}else if(!strcmp(ch,"2")){
while(1){
printf("[%s]수신모드 입니다.\n",arr2->id);
memset(buff, 0x00, sizeof(buff)) ;
read(fd, buff, sizeof(buff));
#ifdef _DEBUG
printf("수신[%s]\n",buff);
#endif
p = strtok(buff,"|");
p2 = strtok(NULL,"|");
p3 = strtok(NULL,"|");
strcpy(arr2->id2,p);
strcpy(arr2->message,p2);
strcpy(arr2->id,p3);
#ifdef _DEBUG_
printf("[%s],[%s]\n",arr1->id,arr2->id);
#endif
if(!strcmp(arr1->id,arr2->id)){
#ifdef _DEBUG_
printf("334567\n");
#endif
EXEC SQL INSERT INTO CHAT_DATA(I,I2,T,B)
VALUES(:arr1->id,:arr2->id2, SYSDATE, :arr2->message);
EXEC SQL COMMIT;
sprintf(buff,"%s|%s|%s",arr2->id2,arr2->message,arr2->flag);
#ifdef _DEBUG_
printf("[%s]\n",buff);
#endif
write(clnt_sock,buff,sizeof(buff));
memset(buff, 0x00, sizeof(buff)) ;
strcpy(ch,"1");
break;
}
}
}
}
free(arr1);
free(arr2);
}
shint의 이미지

https://docs.google.com/presentation/d/1Ft6R7uirfA4A8Vr60o1ETHyMaoTEMz8DcjUoOalXAdU/edit

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.