More actions
imported>hsebs No edit summary |
(Repair batch-0004 pages from live compare) |
||
| (10 intermediate revisions by one other user not shown) | |||
| Line 13: | Line 13: | ||
int thread_num | int thread_num[25]; //스레드 번호 (해당 스레드 활성화시 번호 값 + 1, 비활성화시 0) | ||
//ex) thread_num | //ex) thread_num[스레드 번호]==스레드 번호+1 | ||
int client_socket_array | int client_socket_array[25]; //클라이언트 소캣, 각 스레드 마다 자신의 번호에 해당하는 소캣 사용 | ||
//ex) 스레드가 사용 중인 소캣 == client_socket_array | //ex) 스레드가 사용 중인 소캣 == client_socket_array[스레드 번호] | ||
char id | char id[100][256]; | ||
char password | char password[100][256]; | ||
char id_state | char id_state[100]; | ||
int id_num; | int id_num; | ||
char chat | char chat[100][BUFF_SIZE+5]; | ||
char chat_s | char chat_s[100], chat_e; | ||
void* rutine(void* data)//data = &thread_num | void* rutine(void* data)//data = &thread_num[스레드 번호] | ||
{ | { | ||
int t_num,i_num; | int t_num,i_num;//스레드 번호, 아이디 번호 | ||
int client_socket; | int client_socket; | ||
char buff_rcv | char buff_rcv[BUFF_SIZE+5],buff_snd[BUFF_SIZE+5]; | ||
int rcv; | int rcv; | ||
int i,j; | int i,j; | ||
| Line 40: | Line 40: | ||
//사용자가 이해하기 쉽도록 스레드 번호에 +1 값을 쓰도록 한다. | //사용자가 이해하기 쉽도록 스레드 번호에 +1 값을 쓰도록 한다. | ||
client_socket=client_socket_array | client_socket=client_socket_array[t_num-1]; | ||
//코드의 간결화를 위해 값을 복사한다. | //코드의 간결화를 위해 값을 복사한다. | ||
recv(client_socket, buff_rcv,BUFF_SIZE,0); | recv(client_socket, buff_rcv,BUFF_SIZE,0); | ||
sprintf(buff_snd,"test\n"); | sprintf(buff_snd,"test\n"); | ||
send(client_socket, buff_snd, strlen(buff_snd)+1,0); | send(client_socket, buff_snd, strlen(buff_snd)+1,0); | ||
| Line 54: | Line 53: | ||
//로그인 루프 | //로그인 루프 | ||
recv(client_socket, buff_rcv,BUFF_SIZE,0); | while(1) | ||
if(buff_rcv | { | ||
if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0) | |||
{ | |||
printf("%dth client disconnected\n",t_num); | |||
close(client_socket); | |||
thread_num[t_num-1]=0; | |||
client_socket_array[t_num-1]=0; | |||
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다. | |||
return; | |||
} | |||
if(buff_rcv[0]=='n' || buff_rcv[0]=='l') | |||
{ | |||
sprintf(buff_snd,"a\n"); | |||
send(client_socket, buff_snd, strlen(buff_snd)+1,0); | |||
break; | |||
} | |||
else | |||
{ | |||
printf("wrong data\n"); | |||
sprintf(buff_snd,"c\n"); | |||
send(client_socket, buff_snd, strlen(buff_snd)+1,0); | |||
} | |||
} | |||
if(buff_rcv[0]=='n')//새 계정 생성 | |||
{ | { | ||
printf("client try to make ID\n"); | printf("client try to make ID\n"); | ||
sprintf(buff_snd,"i\n"); | while(1) | ||
{ | |||
sprintf(buff_snd,"i\n"); | |||
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//id 요구 | |||
if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0) | |||
{ | |||
id | printf("%dth client disconnected\n",t_num); | ||
close(client_socket); | |||
thread_num[t_num-1]=0; | |||
client_socket_array[t_num-1]=0; | |||
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다. | |||
return; | |||
} | |||
sprintf(id[id_num],"%s",buff_rcv); | |||
for(i=0;i<id_num;i++) | |||
{ | |||
for(j=0;id[i][j];j++) | |||
{ | |||
if(id[i][j]!=buff_rcv[j]) | |||
break; | |||
} | |||
if(!id[i][j]) | |||
break; | |||
} | |||
if(i==id_num) | |||
{ | |||
break; | |||
} | |||
} | |||
sprintf(buff_snd,"p\n"); | sprintf(buff_snd,"p\n"); | ||
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//password 요구 | send(client_socket, buff_snd, strlen(buff_snd)+1,0);//password 요구 | ||
recv(client_socket, buff_rcv,BUFF_SIZE,0); | if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0) | ||
{ | |||
printf("%dth client disconnected\n",t_num); | |||
close(client_socket); | |||
thread_num[t_num-1]=0; | |||
client_socket_array[t_num-1]=0; | |||
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다. | |||
return; | |||
} | |||
printf("%dth client's password : %s\n",t_num,buff_rcv); | printf("%dth client's password : %s\n",t_num,buff_rcv); | ||
sprintf(password[id_num],"%s",buff_rcv); | |||
i_num=id_num; | i_num=id_num; | ||
id_num++; | id_num++; | ||
printf("%dth client made new ID",t_num); | printf("%dth client made new ID\n",t_num); | ||
sprintf(buff_snd,"a\n"); | sprintf(buff_snd,"a\n"); | ||
| Line 92: | Line 147: | ||
sprintf(buff_snd,"i\n"); | sprintf(buff_snd,"i\n"); | ||
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//id 요구 | send(client_socket, buff_snd, strlen(buff_snd)+1,0);//id 요구 | ||
recv(client_socket, buff_rcv,BUFF_SIZE,0); | if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0) | ||
{ | |||
printf("%dth client disconnected\n",t_num); | |||
close(client_socket); | |||
thread_num[t_num-1]=0; | |||
client_socket_array[t_num-1]=0; | |||
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다. | |||
return; | |||
} | |||
for(i=0;i<id_num;i++) | for(i=0;i<id_num;i++) | ||
{ | { | ||
for(j=0;id | for(j=0;id[i][j];j++) | ||
{ | { | ||
if(id | if(id[i][j]!=buff_rcv[j]) | ||
break; | break; | ||
} | } | ||
if(!id | if(!id[i][j]) | ||
break; | break; | ||
} | } | ||
| Line 106: | Line 170: | ||
continue; | continue; | ||
else | else | ||
if(id_state[i]) | |||
continue; | |||
sprintf(buff_snd,"p\n"); | sprintf(buff_snd,"p\n"); | ||
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//password 요구 | send(client_socket, buff_snd, strlen(buff_snd)+1,0);//password 요구 | ||
recv(client_socket, buff_rcv,BUFF_SIZE,0); | if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0) | ||
{ | { | ||
if(password | printf("%dth client disconnected\n",t_num); | ||
close(client_socket); | |||
thread_num[t_num-1]=0; | |||
client_socket_array[t_num-1]=0; | |||
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다. | |||
return; | |||
} | |||
for(j=0;password[i][j]!='\n';j++) | |||
{ | |||
if(password[i][j]!=buff_rcv[j]) | |||
break; | break; | ||
} | } | ||
if(!password | if(!password[i][j]) | ||
printf("%dth client's password : %s\n",t_num,buff_rcv); | |||
else | |||
continue; | continue; | ||
printf("%dth client logined\n",t_num); | |||
sprintf(buff_snd,"a\n"); | sprintf(buff_snd,"a\n"); | ||
| Line 127: | Line 202: | ||
i_num=i; | i_num=i; | ||
break; | |||
} | } | ||
} | } | ||
sprintf(buff_snd,"%s has joined",id[i_num]); | |||
for(i=0;i<20;i++) | |||
{ | { | ||
sprintf(buff_snd,"%s\n",chat | if(thread_num[i]) | ||
send(client_socket_array[i],buff_snd,strlen(buff_snd)+1,0); | |||
} | |||
id_state[i_num]=1; | |||
for(;chat_s[i_num]!=chat_e;chat_s[i_num]++) | |||
{ | |||
sprintf(buff_snd,"%s\n",chat[chat_s[i_num]]); | |||
send(client_socket, buff_snd, strlen(buff_snd)+1,0); | send(client_socket, buff_snd, strlen(buff_snd)+1,0); | ||
} | } | ||
| Line 145: | Line 230: | ||
{ | { | ||
printf("received\n"); | printf("received\n"); | ||
sprintf(buff_snd,"% | sprintf(buff_snd,"%s : %s",id[i_num],buff_rcv); | ||
for(i=0;i<20;i++) | for(i=0;i<20;i++) | ||
{ | { | ||
if(thread_num | if(thread_num[i]) | ||
send(client_socket_array | send(client_socket_array[i],buff_snd,strlen(buff_snd)+1,0); | ||
} | } | ||
for(i=0;i< | |||
sprintf(chat[chat_e],"%s",buff_snd); | |||
if( | |||
chat_e++; | |||
chat_e%=100; | |||
for(i=0;i<100;i++) | |||
if(id_state[i] || i>=id_num) | |||
chat_s[i]=chat_e; | |||
} | } | ||
else | else | ||
| Line 167: | Line 254: | ||
} | } | ||
printf("disconnected\n"); | |||
sprintf(buff_snd,"%s has left",id[i_num]); | |||
for(i=0;i<20;i++) | |||
{ | |||
if(thread_num[i]) | |||
send(client_socket_array[i],buff_snd,strlen(buff_snd)+1,0); | |||
} | |||
printf("disconnected\n"); | printf("disconnected\n"); | ||
close(client_socket); | close(client_socket); | ||
thread_num | thread_num[t_num-1]=0; | ||
client_socket_array | client_socket_array[t_num-1]=0; | ||
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다. | //스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다. | ||
id_state | id_state[i_num]=0; | ||
} | } | ||
| Line 178: | Line 272: | ||
{ | { | ||
int server_socket; | int server_socket; | ||
pthread_t p_thread | pthread_t p_thread[25]; | ||
struct sockaddr_in server_addr; | struct sockaddr_in server_addr; | ||
struct sockaddr_in client_addr; | struct sockaddr_in client_addr; | ||
| Line 206: | Line 300: | ||
for(i=0;i<20;i++) | for(i=0;i<20;i++) | ||
thread_num | thread_num[i]=0; | ||
while(1) | while(1) | ||
| Line 217: | Line 311: | ||
for(i=0;i<20;i++) | for(i=0;i<20;i++) | ||
{ | { | ||
if(!thread_num | if(!thread_num[i]) | ||
{ | { | ||
client_addr_size= sizeof(client_addr); | client_addr_size= sizeof(client_addr); | ||
client_socket_array | client_socket_array[i] = accept(server_socket, (struct sockaddr*)&client_addr,&client_addr_size); | ||
thread_num | thread_num[i]=i+1; | ||
memset(&p_thread | memset(&p_thread[i],0,sizeof(p_thread[i])); | ||
pthread_create(&p_thread | pthread_create(&p_thread[i],NULL,rutine,(void *)&thread_num[i]); | ||
break; | break; | ||
} | } | ||
| Line 235: | Line 329: | ||
} | } | ||
== 클라이언트 == | == 클라이언트 == | ||
#include<stdio.h> | |||
#include<stdlib.h> | |||
#include<unistd.h> | |||
#include<string.h> | |||
#include<sys/types.h> | |||
#include<sys/socket.h> | |||
#include<arpa/inet.h> | |||
#include<pthread.h> | |||
#define BUFF_SIZE 1024 | |||
void gotoxy(int x,int y) | |||
{ | |||
printf("\033[%d;%df",y,x); | |||
//터미널 출력 위치 변경 함수, y값이 화면 길이보다 크면 화면 길이로 처리된다.(버그의 원인) | |||
fflush(stdout); | |||
} | |||
int client_socket; | |||
int check; | |||
void* rcv_thread(void *data) | |||
{ | |||
int i; | |||
char buff_rcv[BUFF_SIZE+5]; | |||
int rcv; | |||
while(1) | |||
{ | |||
rcv=recv(client_socket, buff_rcv, BUFF_SIZE, 0); | |||
if(rcv>0) | |||
{ | |||
while(check==1); | |||
check=2; | |||
for(i=0;i<rcv;) | |||
{ | |||
gotoxy(0,100);//gotoxy의 특징을 이용하여 화면을 한칸 올린다. | |||
printf("\n"); | |||
gotoxy(0,14); | |||
printf(" "); | |||
gotoxy(0,14); | |||
printf("%s",&buff_rcv[i]); | |||
i+=strlen(&buff_rcv[i])+1; | |||
} | |||
} | |||
else | |||
{ | |||
printf("disconnected\n"); | |||
break; | |||
} | |||
gotoxy(0,15); | |||
printf("write message to send : "); | |||
gotoxy(25,15); | |||
check=0; | |||
} | |||
} | |||
void* snd_thread(void *data) | |||
{ | |||
char buff_snd[BUFF_SIZE+5]; | |||
fgets(buff_snd,BUFF_SIZE,stdin);//버퍼 청소 | |||
while(1) | |||
{ | |||
while(check==2); | |||
check=1; | |||
gotoxy(0,15); | |||
printf("write message to send : "); | |||
gotoxy(25,15); | |||
check=0; | |||
fgets(buff_snd,BUFF_SIZE,stdin); | |||
check=0; | |||
if(send(client_socket, buff_snd, strlen(buff_snd)+1,0)<=0) | |||
{ | |||
printf("disconnected\n"); | |||
break; | |||
} | |||
} | |||
} | |||
int main() | |||
{ | |||
struct sockaddr_in server_addr; | |||
char buff_snd[BUFF_SIZE+5]; | |||
char buff_rcv[BUFF_SIZE+5]; | |||
int rcv; | |||
int i; | |||
pthread_t p_thread[2]; | |||
client_socket=socket(PF_INET, SOCK_STREAM, 0); | |||
if(client_socket==-1) | |||
{ | |||
printf("socket error\n"); | |||
return 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("connect error\n"); | |||
return 1; | |||
} | |||
//연결 확인 | |||
sprintf(buff_snd,"test\n"); | |||
send(client_socket, buff_snd, strlen(buff_snd)+1,0); | |||
if(recv(client_socket, buff_rcv,BUFF_SIZE,0)>0) | |||
{ | |||
printf("connecting succesed\n"); | |||
} | |||
else | |||
{ | |||
printf("disconnected\n"); | |||
close(client_socket); | |||
return 0; | |||
} | |||
//로그인 시스템 | |||
while(1) | |||
{ | |||
printf("new id=n / login=l : "); | |||
scanf("%s",buff_snd); | |||
send(client_socket,buff_snd,strlen(buff_snd)+1,0); | |||
while(1) | |||
{ | |||
if(recv(client_socket,buff_rcv,BUFF_SIZE,0)<=0) | |||
{ | |||
printf("disconnected\n"); | |||
close(client_socket); | |||
return 0; | |||
} | |||
if(buff_rcv[0]=='a'|| buff_rcv[0]=='c') | |||
break; | |||
} | |||
if(buff_rcv[0]=='a') | |||
break; | |||
} | |||
while(1) | |||
{ | |||
if(recv(client_socket,buff_rcv,BUFF_SIZE,0)>0) | |||
{ | |||
switch(buff_rcv[0]) | |||
{ | |||
case 'i' : | |||
printf("ID : "); | |||
scanf("%s",buff_snd); | |||
send(client_socket,buff_snd,strlen(buff_snd)+1,0); | |||
break; | |||
case 'p' : | |||
printf("PASSWORD : "); | |||
scanf("%s",buff_snd); | |||
send(client_socket,buff_snd,strlen(buff_snd)+1,0); | |||
break; | |||
} | |||
if( buff_rcv[0] == 'a' ) | |||
break; | |||
} | |||
else | |||
{ | |||
printf("disconnected\n"); | |||
close(client_socket); | |||
return 0; | |||
} | |||
} | |||
memset(&p_thread[0],0,sizeof(p_thread[0])); | |||
pthread_create(&p_thread[0],NULL,rcv_thread,(void *)NULL); | |||
memset(&p_thread[1],0,sizeof(p_thread[1])); | |||
pthread_create(&p_thread[1],NULL,snd_thread,(void *)NULL); | |||
pthread_join(p_thread[0],(void**)&rcv); | |||
pthread_join(p_thread[1],(void**)&rcv); | |||
close(client_socket); | |||
return 0; | |||
} | |||
== 설명 == | |||
서버를 기반으로한 로그인 시스템의 다중 채팅. 아이디로 재접속시 퇴장 시점부터 재접속까지의 대화 기록을 보여준다. | |||
Latest revision as of 00:37, 27 March 2026
서버
#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 BUFF_SIZE 1024
int thread_num[25]; //스레드 번호 (해당 스레드 활성화시 번호 값 + 1, 비활성화시 0)
//ex) thread_num[스레드 번호]==스레드 번호+1
int client_socket_array[25]; //클라이언트 소캣, 각 스레드 마다 자신의 번호에 해당하는 소캣 사용
//ex) 스레드가 사용 중인 소캣 == client_socket_array[스레드 번호]
char id[100][256];
char password[100][256];
char id_state[100];
int id_num;
char chat[100][BUFF_SIZE+5];
char chat_s[100], chat_e;
void* rutine(void* data)//data = &thread_num[스레드 번호]
{
int t_num,i_num;//스레드 번호, 아이디 번호
int client_socket;
char buff_rcv[BUFF_SIZE+5],buff_snd[BUFF_SIZE+5];
int rcv;
int i,j;
t_num=*((int*)data);
//사용자가 이해하기 쉽도록 스레드 번호에 +1 값을 쓰도록 한다.
client_socket=client_socket_array[t_num-1];
//코드의 간결화를 위해 값을 복사한다.
recv(client_socket, buff_rcv,BUFF_SIZE,0);
sprintf(buff_snd,"test\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);
printf("%dth client connected\n",t_num);
//접속 검사 코드
//로그인 루프
while(1)
{
if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0)
{
printf("%dth client disconnected\n",t_num);
close(client_socket);
thread_num[t_num-1]=0;
client_socket_array[t_num-1]=0;
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다.
return;
}
if(buff_rcv[0]=='n' || buff_rcv[0]=='l')
{
sprintf(buff_snd,"a\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);
break;
}
else
{
printf("wrong data\n");
sprintf(buff_snd,"c\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);
}
}
if(buff_rcv[0]=='n')//새 계정 생성
{
printf("client try to make ID\n");
while(1)
{
sprintf(buff_snd,"i\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//id 요구
if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0)
{
printf("%dth client disconnected\n",t_num);
close(client_socket);
thread_num[t_num-1]=0;
client_socket_array[t_num-1]=0;
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다.
return;
}
sprintf(id[id_num],"%s",buff_rcv);
for(i=0;i<id_num;i++)
{
for(j=0;id[i][j];j++)
{
if(id[i][j]!=buff_rcv[j])
break;
}
if(!id[i][j])
break;
}
if(i==id_num)
{
break;
}
}
sprintf(buff_snd,"p\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//password 요구
if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0)
{
printf("%dth client disconnected\n",t_num);
close(client_socket);
thread_num[t_num-1]=0;
client_socket_array[t_num-1]=0;
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다.
return;
}
printf("%dth client's password : %s\n",t_num,buff_rcv);
sprintf(password[id_num],"%s",buff_rcv);
i_num=id_num;
id_num++;
printf("%dth client made new ID\n",t_num);
sprintf(buff_snd,"a\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//접속 확인
}
else
{
printf("client try to login\n");
while(1)
{
sprintf(buff_snd,"i\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//id 요구
if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0)
{
printf("%dth client disconnected\n",t_num);
close(client_socket);
thread_num[t_num-1]=0;
client_socket_array[t_num-1]=0;
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다.
return;
}
for(i=0;i<id_num;i++)
{
for(j=0;id[i][j];j++)
{
if(id[i][j]!=buff_rcv[j])
break;
}
if(!id[i][j])
break;
}
if(i==id_num)
continue;
else
if(id_state[i])
continue;
sprintf(buff_snd,"p\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//password 요구
if(recv(client_socket, buff_rcv,BUFF_SIZE,0)<=0)
{
printf("%dth client disconnected\n",t_num);
close(client_socket);
thread_num[t_num-1]=0;
client_socket_array[t_num-1]=0;
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다.
return;
}
for(j=0;password[i][j]!='\n';j++)
{
if(password[i][j]!=buff_rcv[j])
break;
}
if(!password[i][j])
printf("%dth client's password : %s\n",t_num,buff_rcv);
else
continue;
printf("%dth client logined\n",t_num);
sprintf(buff_snd,"a\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);//접속 확인
i_num=i;
break;
}
}
sprintf(buff_snd,"%s has joined",id[i_num]);
for(i=0;i<20;i++)
{
if(thread_num[i])
send(client_socket_array[i],buff_snd,strlen(buff_snd)+1,0);
}
id_state[i_num]=1;
for(;chat_s[i_num]!=chat_e;chat_s[i_num]++)
{
sprintf(buff_snd,"%s\n",chat[chat_s[i_num]]);
send(client_socket, buff_snd, strlen(buff_snd)+1,0);
}
while(1)
{
rcv=recv(client_socket,buff_rcv,BUFF_SIZE,0);
if(rcv>0)
{
printf("received\n");
sprintf(buff_snd,"%s : %s",id[i_num],buff_rcv);
for(i=0;i<20;i++)
{
if(thread_num[i])
send(client_socket_array[i],buff_snd,strlen(buff_snd)+1,0);
}
sprintf(chat[chat_e],"%s",buff_snd);
chat_e++;
chat_e%=100;
for(i=0;i<100;i++)
if(id_state[i] || i>=id_num)
chat_s[i]=chat_e;
}
else
{
break;
}
}
printf("disconnected\n");
sprintf(buff_snd,"%s has left",id[i_num]);
for(i=0;i<20;i++)
{
if(thread_num[i])
send(client_socket_array[i],buff_snd,strlen(buff_snd)+1,0);
}
printf("disconnected\n");
close(client_socket);
thread_num[t_num-1]=0;
client_socket_array[t_num-1]=0;
//스레드가 비활성화 되었으므로 thread_num을 0으로 초기화한다.
id_state[i_num]=0;
}
int main()
{
int server_socket;
pthread_t p_thread[25];
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int client_addr_size;
int i;
server_socket=socket(PF_INET, SOCK_STREAM, 0);
if(server_socket==-1)
{
printf("socket error\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=htonl(INADDR_ANY);
if(-1==bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))
{
printf("bind error\n");
exit(1);
}
printf("server started\n");
for(i=0;i<20;i++)
thread_num[i]=0;
while(1)
{
if(-1==listen(server_socket,5))
{
printf("listen error\n");
exit(1);
}
for(i=0;i<20;i++)
{
if(!thread_num[i])
{
client_addr_size= sizeof(client_addr);
client_socket_array[i] = accept(server_socket, (struct sockaddr*)&client_addr,&client_addr_size);
thread_num[i]=i+1;
memset(&p_thread[i],0,sizeof(p_thread[i]));
pthread_create(&p_thread[i],NULL,rutine,(void *)&thread_num[i]);
break;
}
}
if(i==20)
printf("error : Too many clients connected");
}
close(server_socket);
return 0;
}
클라이언트
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<pthread.h>
#define BUFF_SIZE 1024
void gotoxy(int x,int y)
{
printf("\033[%d;%df",y,x);
//터미널 출력 위치 변경 함수, y값이 화면 길이보다 크면 화면 길이로 처리된다.(버그의 원인)
fflush(stdout);
}
int client_socket;
int check;
void* rcv_thread(void *data)
{
int i;
char buff_rcv[BUFF_SIZE+5];
int rcv;
while(1)
{
rcv=recv(client_socket, buff_rcv, BUFF_SIZE, 0);
if(rcv>0)
{
while(check==1);
check=2;
for(i=0;i<rcv;)
{
gotoxy(0,100);//gotoxy의 특징을 이용하여 화면을 한칸 올린다.
printf("\n");
gotoxy(0,14);
printf(" ");
gotoxy(0,14);
printf("%s",&buff_rcv[i]);
i+=strlen(&buff_rcv[i])+1;
}
}
else
{
printf("disconnected\n");
break;
}
gotoxy(0,15);
printf("write message to send : ");
gotoxy(25,15);
check=0;
}
}
void* snd_thread(void *data)
{
char buff_snd[BUFF_SIZE+5];
fgets(buff_snd,BUFF_SIZE,stdin);//버퍼 청소
while(1)
{
while(check==2);
check=1;
gotoxy(0,15);
printf("write message to send : ");
gotoxy(25,15);
check=0;
fgets(buff_snd,BUFF_SIZE,stdin);
check=0;
if(send(client_socket, buff_snd, strlen(buff_snd)+1,0)<=0)
{
printf("disconnected\n");
break;
}
}
}
int main()
{
struct sockaddr_in server_addr;
char buff_snd[BUFF_SIZE+5];
char buff_rcv[BUFF_SIZE+5];
int rcv;
int i;
pthread_t p_thread[2];
client_socket=socket(PF_INET, SOCK_STREAM, 0);
if(client_socket==-1)
{
printf("socket error\n");
return 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("connect error\n");
return 1;
}
//연결 확인
sprintf(buff_snd,"test\n");
send(client_socket, buff_snd, strlen(buff_snd)+1,0);
if(recv(client_socket, buff_rcv,BUFF_SIZE,0)>0)
{
printf("connecting succesed\n");
}
else
{
printf("disconnected\n");
close(client_socket);
return 0;
}
//로그인 시스템
while(1)
{
printf("new id=n / login=l : ");
scanf("%s",buff_snd);
send(client_socket,buff_snd,strlen(buff_snd)+1,0);
while(1)
{
if(recv(client_socket,buff_rcv,BUFF_SIZE,0)<=0)
{
printf("disconnected\n");
close(client_socket);
return 0;
}
if(buff_rcv[0]=='a'|| buff_rcv[0]=='c')
break;
}
if(buff_rcv[0]=='a')
break;
}
while(1)
{
if(recv(client_socket,buff_rcv,BUFF_SIZE,0)>0)
{
switch(buff_rcv[0])
{
case 'i' :
printf("ID : ");
scanf("%s",buff_snd);
send(client_socket,buff_snd,strlen(buff_snd)+1,0);
break;
case 'p' :
printf("PASSWORD : ");
scanf("%s",buff_snd);
send(client_socket,buff_snd,strlen(buff_snd)+1,0);
break;
}
if( buff_rcv[0] == 'a' )
break;
}
else
{
printf("disconnected\n");
close(client_socket);
return 0;
}
}
memset(&p_thread[0],0,sizeof(p_thread[0]));
pthread_create(&p_thread[0],NULL,rcv_thread,(void *)NULL);
memset(&p_thread[1],0,sizeof(p_thread[1]));
pthread_create(&p_thread[1],NULL,snd_thread,(void *)NULL);
pthread_join(p_thread[0],(void**)&rcv);
pthread_join(p_thread[1],(void**)&rcv);
close(client_socket);
return 0;
}
설명
서버를 기반으로한 로그인 시스템의 다중 채팅. 아이디로 재접속시 퇴장 시점부터 재접속까지의 대화 기록을 보여준다.