c언어 tcp소켓 코딩 좀 알려주세요...

zzzalxl의 이미지

조건)유닉스 클라끼리 실시간 채팅하는 프로그램인데
멀티프로세스방식과 fork문을 써서
table1에다가 회원가입된 id, pw, 접속확인을 담고
table2에다가 채팅중인 id1, id2, date, 채팅내용을
담아야됩니다.
그리고 서버 접속시 회원가입과 로그인을 담아
pw는 10자리미만이면 오류, 영어숫자조합 대소문자구분X
3회오류시에 클라 종료되고, 다시 이 아이디로 접속시 3회오류
pw변경을하라는 정보를 담아야됩니다.
중요한건 클라끼리 실시간으로 채팅을 해야한다는건데
너무 어렵습니다..도움좀 주세요 하다가 막혔어요..

(server)
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>    	/* close(), write(), read() */
#include <arpa/inet.h> 	/* socket(), bind(), listen(), accept(), connect() 	*/
#include <sys/socket.h>	/*													*/
#include <sys/types.h>	/*											open() 	*/
#include <sys/stat.h> 
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/sem.h>
#include <malloc.h>
 
#define INITCHAR(x) memset(x,0x00,sizeof(x))
#define PORT 2100      /* 포트 번호 고정 */
#define BUFSIZE 1024
 
EXEC SQL INCLUDE SQLCA;
 
void error_handling(char *message);
void z_handler(int sig);
int echo_serv(int clnt_sock);
 
int main(int argc, char **argv)
{
	int clnt_len;
 	int serv_sock;
  	int clnt_sock;
  	struct sockaddr_in serv_addr;
  	struct sockaddr_in clnt_addr;
  	time_t s_time;
  	char a[100],b[100];
  	int addr_size, str_len, state;
  	pid_t pid;
  	char message[BUFSIZE];
  	struct sigaction act;
  	act.sa_handler=z_handler;
  	sigemptyset(&act.sa_mask);
  	act.sa_flags=0;
 
  	Connect_Oracle();
 	daemon_init(); /* 데몬 */  
 
 	state=sigaction(SIGCHLD, &act, 0); /* 시그널 핸들러 등록 */
	if(state != 0){
		puts("sigaction() error");
		exit(1);
  	} 	
  	serv_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=htonl(INADDR_ANY);
  	serv_addr.sin_port=htons(PORT);
 
  	if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1)
  		error_handling("bind() error");
 
  	if(listen(serv_sock, 5)==-1)
    	error_handling("listen() error");
 
	for(;;){
		clnt_len = sizeof(clnt_addr);
		clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_len);
		if(serv_sock == -1){
			error_handling("accept() error");
		}
		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);
			printf("!!!연결 종료!!!\n");
			close(clnt_sock);
			return(0);
		}else{                      /* 자식 프로세스의 경우 */
			close(clnt_sock) ;
		}	
 
	}
	Commit_Oracle();
	close(clnt_sock);
 
	return(0);
}
 
int daemon_init()
{
	pid_t pid;
	if((pid = fork()) < 0)
   	return(-1);
   	else if(pid != 0)
   		exit(0); /* 부모프로세스는 종료시킨다 */		
	/* child continues */
   		setsid();        /* 스스로 세션의 리더가 된다 */
		umask(0);        /* clear our file mode creation mask */
		return(0);
}
 
void error_handling(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);
  printf("소멸된 좀비의 프로세스 ID : %d \n", pid);
  printf("리턴된 데이터 : %d \n\n", WEXITSTATUS(rtn));  
}
 
int Connect_Oracle(void)
{
 
	EXEC SQL BEGIN DECLARE SECTION;
		char uname[20];
		char passwd[20];	
	EXEC SQL END DECLARE SECTION;
		INITCHAR(uname);
		INITCHAR(passwd);
		strcpy(uname,"zipcode");
		strcpy(passwd,"zipcode");
	EXEC SQL CONNECT :uname IDENTIFIED BY :passwd;	
		if(sqlca.sqlcode != 0){
			printf(" DB CONNECT ERROR \n", sqlca.sqlcode);
			return(1);
		}else{
			printf(" DB CONNECT SUCCESS \n");
		}
		return(0);
}
 
int Commit_Oracle(void)
{
EXEC SQL COMMIT WORK RELEASE;
	printf("DB 접속 종료\n");
	return(0);
}
 
int echo_serv(int clnt_sock)
{
EXEC SQL BEGIN DECLARE SECTION;
	char ch[BUFSIZE];
	int str_len1;
	time_t s_time;
	char *id,*id2,*a,*b,*s,*s1;
EXEC SQL END DECLARE SECTION;
	struct eservstruct{
		char id[20];
		char id2[20];
		char pw[20];
		char message[BUFSIZE];
	};
	char buff[1000];
	struct eservstruct *i;		
	i = (struct eservstruct*) malloc( sizeof(struct eservstruct));
	memset(i, 0x00, sizeof(struct eservstruct));
	/* 자식 프로세스의 처리 영역: 데이터 수신 및 전송 */
	while(str_len1=read(clnt_sock,buff, sizeof(buff)) != 0){		
		s = strtok(buff,"|");
		s1 = strtok(NULL,"|");
		strcpy(i->id,s);
		strcpy(i->message,s1);
 
		time(&s_time);
		printf("접속중인 ID : [%s]\n", i->id);
		printf("메시지 수신시간 : %s", ctime(&s_time));
		/*printf("[%s]\n",message);*/
 
		printf("입력받은 메시지 : %s\n",i->message);
		printf("전달할 메시지 : %s\n\n",i->message);
 
		EXEC SQL INSERT INTO ECHO_SERV(I,T,A,B) 
		VALUES(:i->id, SYSDATE, :i->message, :i->message);
 
		EXEC SQL COMMIT;
 
		write(clnt_sock,i->message, str_len1); 
		memset(buff, 0x00, sizeof(buff));
	}
	free(i);		
}
 
 
(client)
#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 <ctype.h> /* 문자 함수 */
 
#define BUFSIZE 1024
#define PORT 2100
void error_handling(char *message);
int join(int *new_num, char *id, char *pw);
 
int main(int argc, char **argv)
{
	int *num;
	char isalpha, isdigit;/* 영숫자 */
	int k=0;
	int a,n = 0;
	int i=0;
	char *id1;
	char *pw1;
	char new_check[10];
	int new_num;
	char *pw3;
	int pwcnt=0;
	char message[BUFSIZE];
  	int sock;
  	pid_t pid;
  	int str_len, recv_len, recv_num;
  	struct sockaddr_in serv_addr;
  	char buff[1000];
  	typedef struct{
	  	char id[20];
 	 	char pw[20];
 	 	char message[BUFSIZE];
 	 	char flag[100];
  	}clntstruct;  	
  	sock=socket(PF_INET, SOCK_STREAM, 0);
 
	clntstruct *j;
	j = malloc(sizeof(clntstruct));	   
 
  	memset(&serv_addr, 0, sizeof(serv_addr));
  	serv_addr.sin_family=AF_INET;
  	serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
  	serv_addr.sin_port=htons(PORT);
 
  	if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1){
    	error_handling("connect() error!");
	}
 
	while(1){
		input :	printf("[1]회원가입 [2]로그인\n");
			scanf("%d",&k);
 
			if(k==1){/* 회원가입 */
				printf("New ID : ");
				scanf("%s",j->id);	
				printf("New PW : ");
				scanf("%s",j->pw);
 
				while(strlen(gets(j->pw))<10){               /* pw 10자리 미만 오류 */
					printf("PW ERROR\n");
					memset(j->pw, 0x00, sizeof(j->pw));
					printf("New PW : ");
				}
 
/*				if(isdigit(j->pw)) && (isalpha(j->pw)){                     /* 영,숫자만 한글 오류*/
/*					printf("PW ERROR\n");
					memset(j->pw, 0x00, sizeof(j->pw));
					return(0);
				} 		*/
/*			printf("pw : ");  */
				goto input;
			}
 
			else if(k==2){ /* 로그인 */
				printf("ID : ");
				scanf("%s",j->id);
				printf("PW : ");
				scanf("%s",j->pw);
 
				while(strlen(gets(j->id))>20){
					printf("ID ERROR\n");
					memset(j->id, 0x00, sizeof(j->id));
					printf("ID : ");
				}
					while(strlen(gets(j->pw))<10){              /* pw 10자리 미만 오류 */
						printf("PW ERROR\n");
					memset(j->pw, 0x00, sizeof(j->pw));
					printf("PW : ");
					}
 
					while(1){                                  /* 3회 오류 */
//						printf("PW ERROR\n");
						pwcnt++;
						memset(buff,0x00,sizeof(buff));
						if(pwcnt == 3){
							strcpy(j->flag,pw3);
							sprintf(buff,"%s|%s|%s",j->id,j->pw,j->flag);
							write(sock, buff, sizeof(buff));
							printf("PW 3 ERROR\n");
							return(0);
						}
//						memset(j->pw, 0x00, sizeof(j->pw));
//						printf("PW : ");
							sprintf(buff,"%s|%s|%s|",j->id,j->pw,j->flag);
							write(sock, buff, sizeof(buff));
							memset(buff,0x00,sizeof(buff));
							read(sock, buff, sizeof(buff));
							if(strcmp(buff,"p")){
								break;
							}
					}			
		/*			strcpy(id1,id);
					strcpy(pw1,pw);    */
					goto end;
			}
			end : printf("채팅접속!!\n");	
 
 
 
	while(1){
		fflush(stdin);
		printf("전송할 메시지를 입력하세요 (q,Q to quit) : ");
 
		if(strlen(gets(j->message))>BUFSIZE){
			printf("error");
			break;
		}
			if(!strcmp(j->message,"q")){
				break;
			}else if(!strcmp(j->message,"Q")){	
				break;
			}
			strcpy(buff,j->id);
			strcat(buff,"|");
			strcat(buff,j->message);
			strcat(buff,"|");		
			str_len=write(sock, buff, sizeof(buff));
			str_len = read(sock, j->message, sizeof(j->message));
			printf("서버로부터 전송된 메시지 : %s\n",j->message);
			memset(j->message,0x00,sizeof(j->message));
	}
	free(j);
	printf("CLIENT EXIT!!\n");
	close(sock);
	return(0);
	}
}
 
 
void error_handling(char *message)
{
	fputs(message, stderr);
  	fputc('\n', stderr);
  	exit(1);
}

snowall의 이미지

어디서 막혔는데요?

피할 수 있을때 즐겨라! http://melotopia.net/b

shint의 이미지

이런것들이 있는거 같습니다.

//
1. fork가 어렵다면. 프로세스를 두개로 나눠서 띄우는 방법도 있습니다. 하나는 table1 전용. 하나는 table2 전용.

//IPC를 사용하는 방법도 있을까 싶습니다.
http://tomyoke.tistory.com/entry/IPC-%EA%B4%80%EB%A0%A8-pdf

2. 손쉽게는 만들어진 채팅 소스를 사용하는 방법도 있습니다. php 채팅 서버 (네이버에서 php 채팅소스 찾으면 여러가지 나옵니다.)

3. 실시간에 관련된 글
http://kldp.org/node/134425

//그외의 다양한 방법들

//PHP AJAX 채팅 서버 구현하기
http://www.nickspace.cn/xe/blog/textyle/168
http://blog.naver.com/mewizard?Redirect=Log&logNo=20065060654
http://blog.naver.com/kimgudtjr?Redirect=Log&logNo=140108861301
http://blog.naver.com/seogi1004?Redirect=Log&logNo=110098886402
http://cafe.naver.com/gogoomas/165025
http://cafe.naver.com/eztcp/255

//Flash RTMP등으로 P2P를 지원 해줍니다.
http://kreun.blog.me/130137681742
http://kreun.blog.me/130132868864
http://storyjava.tistory.com/23
http://jasu.tistory.com/545
http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=10402&docId=76694033&qb=UlRNRlA=&enc=utf8&section=kin&rank=1&search_sort=0&spq=0&pid=R6NcRU5Y7uossuB3ZKwssssssso-442057&sid=UKcHEnJvLBYAAE@1DjE
http://kldp.org/node/134476
http://kldp.org/node/111009

//RED5

//실버라이트 채팅 서버 구현하기
http://dingpong.net/tt/179

//Web RTC
http://nurinamu.tistory.com/601
ICE Google talk data center
VP8 free royalty G.711

http://kldp.org/node/37324

//Web Socket
http://cafe.naver.com/buldon/4154

//JAVA WAS
http://blog.naver.com/necrosis?Redirect=Log&logNo=140142143118
http://blog.naver.com/necrosis?Redirect=Log&logNo=140142143118

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

매일 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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.