채팅프로그램 구현중 오류
글쓴이: ch0nn0m / 작성시간: 월, 2010/08/23 - 6:22오후
리눅스 상에서 채팅프로그램을 구현했는데요...
컴파일까지는 에러없이 잘 진행이 되었는데...
실행을 하게 되면...
서버측에서 세그멘테이션 오류가 나오면서 끊겨버리네요...
어디가 잘못된것인지요??
server.c
/*
연결리스트로 구현하여 무한의 유저 수와 방 개수 가질 수 있는 채팅서버
- 각 방이 가지는 유저에 대해서는 구조체로 관리
동시처리에 대해서는 select이용
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
/*
유저가 가질수 있는 데이터
: 대화명(귓속말등 기타 기능 추가시 서버에서 관리) / 소켓 기술자 / 다음 유저(연결리스트)
*/
struct user_node
{
char user_name[30];
int user_sockfd;
struct user_node *next_user;
};
/*
Linked List로 유저에 대한 동적인 할당
방이 가지는 데이터 : 방인원수 / 방이름 / 다음 방 노드 포인터 / 사용자 데이터
*/
struct room_node
{
int user_count;
char room_name[30];
struct room_node *next_room;
struct user_node *user;
};
typedef struct user_node user;
typedef struct room_node room;
int Socket(int family, int type, int protocol);
void Bind (int sockfd, const struct sockaddr * socketaddr, socklen_t addrlen);
void Listen(int sockfd, int backlog);
int Accept(int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen);
//명령어 확인 함수
int command_valid(char *);
int main(int argc, char * argv[])
{
//프로그램 실행시 인자 확인
if(argc != 2){
printf("포트번호를 인자로 받아야 함. ex)tcs 22030\n");
exit(1);
}
room *roomlist, *new_node, *temp_node, *prev_node, *make_node;
user *userlist, *new_user, *temp_user, *prev_user, *prev_remove_user;
int server_socket;
int client_socket;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int addrsize, msgsize, all_user_count=0;
char BUFF[1024] = {0};
char temp_char[30];
fd_set readfd;
int maxfd;
//방번호
int room_index, i, j;
char char_room_index[10] = {10};
int tempsockfd;
//명령어 flag
int order_flag = 0;
//방조인 flag
int join_flag = 0;
int join_num = 0;
//사용자 중복 flag
int user_flag = 0;
//1:1대화
char talk_user[30];
char char_talk_port[6];
int talk_port = 0;
int talk_sockfd = 0;
int talk_flag = 0;
new_node = NULL;
temp_node = NULL;
//대기실 설정
roomlist = (room *)malloc(sizeof(room));
memset(roomlist->room_name, '\0', 30);
strcpy(roomlist->room_name, "");
roomlist->user_count = 0;
roomlist->next_room = new_node;
roomlist->user = NULL;
//new_node는 언제나 roomlist만 나타낸다.
new_node = roomlist;
/*1. 서버소켓생성*/
server_socket = Socket(AF_INET, SOCK_STREAM, 0);
/*서버 IP및 포트 설정*/
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[1]));
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&(server_addr.sin_zero), 0, 8);
//소켓 bind
Bind(server_socket, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
//소켓 listen
Listen(server_socket, 0);
while(1)
{
FD_ZERO(&readfd);
maxfd = server_socket;
/*서버에접속한 클라이언트 소켓 기술자[각 방의 유저구조체포함]를 fd_set에 설정*/
FD_SET(server_socket, &readfd);
//첫번째방(대기실)을 지정
roomlist = new_node;
while(roomlist)
{
//각 방의 처음 유저를 지정
temp_user = roomlist->user;
while(temp_user)
{
//사용자들의 소켓 기술자를 설정 / 최대값 저장
tempsockfd = temp_user->user_sockfd;
FD_SET(tempsockfd, &readfd);
if (tempsockfd > maxfd)
maxfd = tempsockfd;
temp_user = temp_user->next_user;
}
roomlist = roomlist->next_room;
}
maxfd = maxfd + 1;
select(maxfd, &readfd, NULL, NULL, NULL);
/*서버로의 접속이 있는 클라이언트에 대한 처리*/
if (FD_ISSET(server_socket, &readfd))
{
addrsize = sizeof(struct sockaddr_in);
client_socket = Accept(server_socket, (struct sockaddr*)&server_addr, &addrsize);
memset(BUFF, '\0', sizeof(BUFF));
msgsize = read(client_socket, BUFF, sizeof(BUFF));
//사용자 이름 중복 확인
roomlist = new_node;
while(roomlist)
{
temp_user = roomlist->user;
while(temp_user)
{
if (strcmp(BUFF, temp_user->user_name)==0) //사용자와 같은 이름을 가진 사람이 있을 경우
user_flag = 1;
temp_user = temp_user->next_user;
}
roomlist = roomlist->next_room;
}
//같은 이름이 존재하는 경우
if(user_flag == 1){
strcat(BUFF, "같은 이름이 존재합니다. 다시 접속해주십시요.\n");
write(client_socket, BUFF, strlen(BUFF));
close(client_socket);
user_flag = 0;
}
//같은 이름이 없을 경우
else{
if (msgsize <=0)
{
printf("Enter user Error\n");
continue;
}
printf("Receive Message:%s\n", BUFF);
//새로운 유저 데이터 공간 할당
new_user = (user *)malloc(sizeof(user));
new_user->user_sockfd = client_socket;
memset(new_user->user_name, '\0', 30);
strcpy(new_user->user_name, BUFF);
roomlist = new_node;
temp_user = roomlist->user;
while(temp_user)
{
prev_user = temp_user;
temp_user = temp_user->next_user;
}
//첫번째로 입장한 경우
if(prev_user == NULL){
roomlist->user = new_user;
new_user->next_user = NULL;
}
//첫번째로 입장한 경우가 아닌 경우
else{
new_user->next_user = prev_user->next_user;
prev_user->next_user = new_user;
}
//방의 인원 증가 / 전체 인원 증가
roomlist->user_count++;
all_user_count++;
printf("현재 접속 인원은 %d명 입니다.\n", all_user_count);
printf("%s가 접속했습니다.\n", new_user->user_name);
memset(BUFF, '\0', sizeof(BUFF));
strcpy(BUFF, "ConnectOK\n");
//현재의 방, 사용자 접속 정보
roomlist = new_node;
room_index = 0;
strcat(BUFF, "############현재 접속 현황############\n");
while(roomlist)
{
if(room_index == 0)
strcat(BUFF, "대기실 ");
else{
sprintf(char_room_index, "%d", room_index); //방번호 문자열로 변환
strcat(BUFF, char_room_index);
strcat(BUFF, "번방 " );
}
strcat(BUFF, roomlist->room_name);
strcat(BUFF, " : ");
temp_user = roomlist->user;
while(temp_user)
{
strcat(BUFF, temp_user->user_name);
strcat(BUFF, ", ");
temp_user = temp_user->next_user;
}
strcat(BUFF, "\n");
roomlist = roomlist->next_room;
++room_index;
}
strcat(BUFF, "########################################\n");
//사용자에게 방, 사용자 접속 정보를 보내줌
write(client_socket, BUFF, strlen(BUFF));
printf("%s\n", BUFF);
continue;
}
}
/*
각 방에 속한 모든 유저들의 소켓 기술자의 변화를 감지하여
해당 수신 데이터에 대한 응답을 같은 방에 있는 유저에 한해서 송신
*/
roomlist = new_node;
prev_node = NULL;
room_index = 0;
while(roomlist)
{
temp_user = roomlist->user;
prev_remove_user = NULL;
while(temp_user)
{
//현재 temp_user에서 데이터 변화가 있을 경우
if (FD_ISSET(temp_user->user_sockfd, &readfd))
{
memset(BUFF, '\0', sizeof(BUFF));
tempsockfd = temp_user->user_sockfd;
msgsize = read(tempsockfd, BUFF, sizeof(BUFF));
//사용자가 없을 경우
if (msgsize <= 0)
{
roomlist->user_count--;
all_user_count--;
printf("%s is out!\n", temp_user->user_name);
//방의 첫번째 포인터에 있는 사용자일 경우
if(prev_remove_user == NULL)
{
roomlist->user = temp_user->next_user;
}
else
{
prev_remove_user->next_user = temp_user->next_user;
}
close(temp_user->user_sockfd);
free(temp_user);
}
//사용자가 메시지를 보냈을 경우
else
{
prev_user = roomlist->user;
printf("Receive Message=>%s\n", BUFF);
msgsize = strlen(BUFF);
//명령어 확인 함수
order_flag = command_valid(BUFF);
switch(order_flag){
case 0 : //보통 대화문
while(prev_user)
{
//같은 방에서 자신을 제외한 사람들에게 메시지를 전송
if(prev_user->user_sockfd != tempsockfd){
write(prev_user->user_sockfd, BUFF, msgsize);
printf("tempusersockfd %d\n", prev_user->user_sockfd);
}
prev_user = prev_user->next_user;
}
break;
case 1 : //방 만들기
//방 설정
make_node = (room *)malloc(sizeof(room));
printf("%s\n", BUFF+6);
memset(make_node->room_name, '\0', 30);
strcpy(make_node->room_name, BUFF+6);
make_node->user_count = 1;
make_node->next_room = roomlist->next_room;
roomlist->next_room = make_node;
roomlist->user_count--; //현재방 인원 감소
//유저 설정
if(prev_remove_user == NULL)
{
roomlist->user = temp_user->next_user;
}
else
{
prev_remove_user->next_user = temp_user->next_user;
}
make_node->user = temp_user;
temp_user->next_user = NULL;
printf("새로운 방이 만들어졌습니다.\n");
strcpy(BUFF, "방을 만들었습니다.");
msgsize = strlen(BUFF);
write(temp_user->user_sockfd, BUFF, msgsize);
break;
case 2 : //방 조인
//들어갈 방 찾기
join_flag = 0;
join_num = atoi(BUFF+6);
temp_node = new_node;
for(i = 0; i < join_num; i++){
temp_node = temp_node->next_room;
join_flag = 1;
}
if(join_flag == 1){
roomlist->user_count--; //현재방 인원 감소
//유저 설정
if(prev_remove_user == NULL)
{
roomlist->user = temp_user->next_user;
}
else
{
prev_remove_user->next_user = temp_user->next_user;
}
new_user = temp_node->user;
while(new_user)
{
prev_user = new_user;
new_user = new_user->next_user;
}
temp_user->next_user = prev_user->next_user;
prev_user->next_user = temp_user;
temp_node->user_count++; //들어가는 방 인원 증가
strcpy(BUFF, "방을 들어갔습니다.");
msgsize = strlen(BUFF);
write(temp_user->user_sockfd, BUFF, msgsize);
}
else
{
strcpy(BUFF, "방을 찾을 수 없습니다.");
msgsize = strlen(BUFF);
write(temp_user->user_sockfd, BUFF, msgsize);
}
break;
case 3 : //방에서 나가기
//방 설정
roomlist->user_count--; //현재방 인원 감소
//유저 설정
if(prev_remove_user == NULL)
{
roomlist->user = temp_user->next_user;
}
else
{
prev_remove_user->next_user = temp_user->next_user;
}
temp_node = new_node;
new_user = temp_node->user;
while(new_user)
{
prev_user = new_user;
new_user = new_user->next_user;
}
temp_user->next_user = prev_user->next_user;
prev_user->next_user = temp_user;
temp_node->user_count++; //들어가는 방 인원 증가
if(roomlist->user_count == 0) //방에 인원이 한명도 없을 경우
{
if(strcmp(roomlist->room_name, "") != 0){
prev_node->next_room = roomlist->next_room;
free(roomlist);
printf("방이 없어졌습니다.\n");
}
}
strcpy(BUFF, "방을 나갔습니다.");
msgsize = strlen(BUFF);
write(temp_user->user_sockfd, BUFF, msgsize);
break;
case 4 : //채팅 종료하기
//방 설정
roomlist->user_count--; //현재방 인원 감소
all_user_count--; //총 인원 감소
printf("%s is out!\n", temp_user->user_name);
//유저 설정
if(prev_remove_user == NULL)
{
roomlist->user = temp_user->next_user;
}
else
{
prev_remove_user->next_user = temp_user->next_user;
}
close(temp_user->user_sockfd);
free(temp_user);
temp_node = new_node;
if(roomlist->user_count == 0) //방에 인원이 한명도 없을 경우
{
if(strcmp(roomlist->room_name, "") != 0){ //대기실이 아닌 경우
prev_node->next_room = roomlist->next_room;
free(roomlist);
printf("방이 없어졌습니다.\n");
}
}
break;
case 5 : //방 현황 보여주기
memset(BUFF, '\0', sizeof(BUFF));
//현재 방, 사용자 접속 정보
temp_node = new_node;
room_index = 0;
strcat(BUFF, "############현재 접속 현황############\n");
while(temp_node)
{
if(room_index == 0)
strcat(BUFF, "대기실 ");
else{
sprintf(char_room_index, "%d", room_index); //방번호 문자열로 변환
strcat(BUFF, char_room_index);
strcat(BUFF, "번방 " );
}
strcat(BUFF, temp_node->room_name);
strcat(BUFF, " : ");
prev_user = temp_node->user;
while(prev_user)
{
strcat(BUFF, prev_user->user_name);
strcat(BUFF, ", ");
prev_user = prev_user->next_user;
}
strcat(BUFF, "\n");
temp_node = temp_node->next_room;
++room_index;
}
strcat(BUFF, "######################################\n");
msgsize = strlen(BUFF);
write(temp_user->user_sockfd, BUFF, msgsize);
break;
case 6 : //1:1대화
//상대편 이름, 채팅 포트 분류
talk_flag = 0;
strcpy(temp_char, BUFF+6);
for(i=0; i<30; i++){
if(temp_char[i] == ' '){
break;
}
talk_user[i] = temp_char[i];
}
talk_user[i] = 0;
for(j=0; j<30; j++){
if(temp_char[i] == 0){
break;
}
char_talk_port[j] = temp_char[i];
i++;
}
char_talk_port[j] = 0;
talk_port = atoi(char_talk_port);
//사용자 이름 찾기
temp_node = new_node;
while(temp_node)
{
prev_user = temp_node->user;
while(prev_user)
{
if (strcmp(talk_user, prev_user->user_name)==0){ //사용자와 같은 이름을 가진 사람이 있을 경우
talk_sockfd = prev_user->user_sockfd;
talk_flag = 1;
}
prev_user = prev_user->next_user;
}
temp_node = temp_node->next_room;
}
if(talk_flag == 1)
{
memset(BUFF, '\0', sizeof(BUFF));
strcpy(BUFF, ".multi");
strcat(BUFF, char_talk_port);
msgsize = strlen(BUFF);
write(talk_sockfd, BUFF, msgsize);
}
else
{
strcat(BUFF, "사용자가 존재하지 않습니다.");
msgsize = strlen(BUFF);
write(temp_user->user_sockfd, BUFF, msgsize);
}
break;
default :
break;
}
}
}
prev_remove_user = temp_user;
temp_user = temp_user->next_user;
}
prev_node = roomlist;
roomlist = roomlist->next_room;
}
}
return 0;
}
int Socket(int family, int type, int protocol)
{
int result = 0;
result = socket(family, type, protocol);
if (result == -1)
{
printf("Socket Contructing Error\n");
exit(0);
}
return result;
}
void Bind(int sockfd, const struct sockaddr * socketaddr, socklen_t addrlen)
{
int result = 0;
result = bind(sockfd, socketaddr, addrlen);
if (result == -1)
{
printf("Socket Binding Error\n");
exit(0);
}
else
{
printf("Success Binding\n");
}
}
void Listen(int sockfd, int backlog)
{
int result = 0;
result = listen(sockfd, backlog);
if (result == -1)
{
printf("Listening Error\n");
exit(0);
}
else
{
printf("Success Listening\n");
}
}
int Accept(int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen)
{
int result = 0;
result = accept(sockfd, cliaddr, addrlen);
if (result == -1)
{
printf("Accept Error\n");
exit(0);
}
else
{
printf("Success Accept\n");
}
return result;
}
//명령어 확인 함수
int command_valid(char *BUFF){
char temp[5];
int i;
for(i = 0; i < 5; i++){
temp[i] = *BUFF;
BUFF++;
}
if(strcmp(temp, ".make")==0){ //방만들기
return 1;
}
else if(strcmp(temp, ".join")==0){ //방조인
return 2;
}
else if(strcmp(temp, ".quit")==0){ //방나가기
return 3;
}
else if(strcmp(temp, ".exit")==0){ //접속 종료
return 4;
}
else if(strcmp(temp, ".show")==0){ //방 / 접속 인원 현황
return 5;
}
else if(strcmp(temp, ".talk")==0){ //1:1대화 신청
return 6;
}
return 0;
}client.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <strings.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
int Socket(int family, int type, int protocol);
void Connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen);
int command_valid(char *, int);
int msg_conf(char *);
void Multicast_exe();
//멀티 채팅용
void* thread_process(void * sockfd);
struct sockaddr_in multicast_group_addr;
struct ip_mreq mreq;
int multi_exit(char *BUFF);
int main(int argc, char * argv[])
{
//실행시 인자 확인
if(argc != 3){
printf("도메인 네임과 포트번호를 인자로 받아야 함. ex)tcs 203.250.148.46 22030\n");
exit(1);
}
struct sockaddr_in connect_addr;
int connect_fd, i, j;
int msgsize;
char name[30] = {0};
char msg[1024] = {0};
fd_set readfd;
int temp_index;
int state_flag = 0; //사용자 위치 flag : 0일 경우 대기실, 1일 경우 방 안
int msg_flag = 0; //보낸 메시지 flag
int rec_flag = 0; //받은 메시지 flag
//1:1 채팅 사용 변수
int multicast_send_sockfd;
int multicast_recv_sockfd;
int multicast_index;
int ttl;
char send_data[1024] = {0};
pthread_t thread;
char user_name[30] = {0};
int send_result;
ttl = 64;
multicast_index = 1;
int rec_port = 0;
char temp_char[30];
char char_talk_port[30];
int talk_port = 0;
printf("#################################\n");
printf("###Welcome to Chatting Browser###\n");
printf("#################################\n");
printf("#Enter User Name=> ");
memset(name, '\0', sizeof(name));
/*사용자 대화명 입력 처리*/
fgets(name,30, stdin);
strcpy(user_name, name); //멀티채팅용 이름
user_name[strlen(user_name)-1] = ']';
name[strlen(name)-1] = '\0';
memset(msg, '\0', sizeof(msg));
for (temp_index = 0; temp_index < strlen(name); temp_index++)
{
msg[temp_index] = name[temp_index];
}
connect_fd = Socket(AF_INET, SOCK_STREAM, 0);
connect_addr.sin_family = AF_INET;
connect_addr.sin_port = htons(atoi(argv[2]));
connect_addr.sin_addr.s_addr = inet_addr(argv[1]);
memset(&(connect_addr.sin_zero), 0, 8);
/*서버 접속*/
Connect(connect_fd, (struct sockaddr*)&connect_addr, sizeof(connect_addr));
msgsize = strlen(msg);
write(connect_fd, msg, msgsize);
memset(msg, '\0', sizeof(msg));
/*채팅 서버에 대한 접속 결과 확인*/
read(connect_fd, msg, sizeof(msg));
printf("########################################\n");
printf("####채팅서버에 접속하셨습니다.##########\n");
printf("########################################\n");
printf("## 방만들기 : .make 방제목 ##\n");
printf("## 방들어가기 : .join 방번호 ##\n");
printf("## 방나가기 : .quit ##\n");
printf("## 접속종료 : .exit ##\n");
printf("## 사용자현황 : .show ##\n");
printf("## 명령어출력 : .help ##\n");
printf("## 귓속말 : .talk 상대방이름 포트번호 ##\n");
printf("########################################\n");
printf("%s\n", msg);
/*수신 데이타의 동시 처리*/
FD_ZERO(&readfd);
while(1)
{
FD_SET(0, &readfd);
FD_SET(connect_fd, &readfd);
select (connect_fd+1, &readfd, NULL, NULL, NULL);
//서버에서 데이터를 받은 경우
if (FD_ISSET(connect_fd, &readfd))
{
memset(msg, '\0', sizeof(msg));
msgsize = read(connect_fd, msg, sizeof(msg));
if (msgsize <= 0)
continue;
//받은 메시지 확인
rec_flag = msg_conf(msg);
//1:1 채팅 요청인 경우
if(rec_flag == 1)
{
//앞의 6개 문자를 제외한 후 포트번호로 할당
rec_port = atoi(msg+6);
/*멀티 캐스트 수신 및 송신 소켓 생성*/
multicast_recv_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
multicast_send_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&multicast_group_addr, 0, sizeof(multicast_group_addr));
/*멀티 캐스트 주소 및 포트 설정*/
multicast_group_addr.sin_family = AF_INET;
multicast_group_addr.sin_port = htons(rec_port); //동적인 포트번호(1:1통신을 할수 있게 해줌)
multicast_group_addr.sin_addr.s_addr = inet_addr("239.100.150.200"); //임의의 멀티캐스트 주소
/*멀티 캐스트 주소와 수신 IP주소 설정*/
mreq.imr_multiaddr = multicast_group_addr.sin_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
multicast_recv_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
/*소켓 옵션 설정 멀티캐스트 그룹 추가*/
setsockopt(multicast_recv_sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
/*소켓 재사용*/
setsockopt(multicast_recv_sockfd, SOL_SOCKET, SO_REUSEADDR, &multicast_index, sizeof(multicast_index));
/*TTL설정*/
setsockopt(multicast_recv_sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
send_result = bind(multicast_recv_sockfd, (struct sockaddr*)&multicast_group_addr, sizeof(multicast_group_addr));
if (send_result < 0)
{
printf("!Bind Error\n");
exit(0);
}
else
{
printf("####################################\n");
printf("## Start 1:1 Chatting Program ##\n");
printf("## 종료명령은 .exit입니다. ##\n");
printf("####################################\n");
}
/*수신 데이타에 대한 Thread 처리*/
pthread_create(&thread, NULL, thread_process, (void*)multicast_recv_sockfd);
while(1)
{
memset(send_data, '\0', sizeof(send_data));
fgets(send_data, sizeof(send_data), stdin);
if(multi_exit(send_data)){
close(multicast_send_sockfd);
close(multicast_recv_sockfd);
printf("멀티 채팅 종료\n");
break;
}
else
{
send_data[strlen(send_data) -1] = '[';
strcat(send_data, user_name);
send_result = sendto(multicast_send_sockfd, send_data, strlen(send_data), 0, (struct sockaddr*)&multicast_group_addr, sizeof(multicast_group_addr));
}
}
}
//대화문인 경우
else
{
printf("%s\n", msg);
}
}
if (FD_ISSET(0, &readfd))
{
memset(msg, '\0', sizeof(msg));
fgets(msg, 1024, stdin);
//보내는 메시지 확인
msg_flag = command_valid(msg, state_flag);
switch(msg_flag)
{
case 0 : //대화문인 경우
if((*msg != '.')){
msg[strlen(msg)-1] = '[';
strcat(msg, name);
msg[strlen(msg)] = ']';
}
msgsize = strlen(msg);
write(connect_fd, msg, msgsize);
break;
case 1 : //에러일 경우 : 데이터를 보내지 않음.
break;
case 2 : //접속 종료인 경우
msgsize = strlen(msg);
write(connect_fd, msg, msgsize);
printf("연결을 종료하겠습니다.\n");
close(connect_fd);
exit(1);
break;
case 3 : //명령어 출력
break;
case 4 : //명령어인 경우(대기실 -> 방안)
msgsize = strlen(msg);
write(connect_fd, msg, msgsize);
state_flag = 1;
break;
case 5 : //명령어인 경우(방안 -> 대기실)
msgsize = strlen(msg);
write(connect_fd, msg, msgsize);
state_flag = 0;
break;
case 6 : //명령어인 경우(위치 변동 없음)
msgsize = strlen(msg);
write(connect_fd, msg, msgsize);
break;
case 7 : //멀티 채팅
//서버에 먼저 데이터를 전송한다.
msgsize = strlen(msg);
write(connect_fd, msg, msgsize);
//채팅 포트 분류
strcpy(temp_char, msg+6);
printf("%s\n", temp_char);
for(i=0; i<30; i++){
if(temp_char[i] == ' '){
break;
}
}
for(j=0; j<30; j++){
if(temp_char[i] == 0){
break;
}
char_talk_port[j] = temp_char[i];
i++;
}
char_talk_port[j] = 0;
talk_port = atoi(char_talk_port);
/*멀티 캐스트 수신 및 송신 소켓 생성*/
multicast_recv_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
multicast_send_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&multicast_group_addr, 0, sizeof(multicast_group_addr));
/*멀티 캐스트 주소 및 포트 설정*/
multicast_group_addr.sin_family = AF_INET;
multicast_group_addr.sin_port = htons(talk_port);
multicast_group_addr.sin_addr.s_addr = inet_addr("239.100.150.200");
/*멀티 캐스트 주소와 수신 IP주소 설정*/
mreq.imr_multiaddr = multicast_group_addr.sin_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
multicast_recv_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
/*소켓 옵션 설정 멀티캐스트 그룹 추가*/
setsockopt(multicast_recv_sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
/*소켓 재사용*/
setsockopt(multicast_recv_sockfd, SOL_SOCKET, SO_REUSEADDR, &multicast_index, sizeof(multicast_index));
/*TTL설정*/
setsockopt(multicast_recv_sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
send_result = bind(multicast_recv_sockfd, (struct sockaddr*)&multicast_group_addr, sizeof(multicast_group_addr));
if (send_result < 0)
{
printf("!Bind Error\n");
exit(0);
}
else
{
printf("####################################\n");
printf("## Start 1:1 Chatting Program ##\n");
printf("## 종료명령은 .exit입니다. ##\n");
printf("####################################\n");
}
/*수신 데이타에 대한 Thread 처리*/
pthread_create(&thread, NULL, thread_process, (void*)multicast_recv_sockfd);
while(1)
{
memset(send_data, '\0', sizeof(send_data));
fgets(send_data, sizeof(send_data), stdin);
if(multi_exit(send_data)){
close(multicast_send_sockfd);
close(multicast_recv_sockfd);
printf("멀티 채팅 종료\n");
break;
}
else
{
send_data[strlen(send_data) -1] = '[';
strcat(send_data, user_name);
send_result = sendto(multicast_send_sockfd, send_data, strlen(send_data), 0, (struct sockaddr*)&multicast_group_addr, sizeof(multicast_group_addr));
}
}
break;
default :
break;
}
}
}
return 0;
}
void Connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen)
{
int result = 0;
result = connect(sockfd, servaddr, addrlen);
if (result == -1)
{
printf("접속을 할 수 없습니다.\n");
exit(0);
}
}
int Socket(int family, int type, int protocol)
{
int result = 0;
result = socket(family, type, protocol);
if (result == -1)
{
printf("Socket Contructing Error\n");
exit(0);
}
return result;
}
int command_valid(char *BUFF, int state_flag){
char temp[5];
int i;
for(i = 0; i < 5; i++){
temp[i] = *BUFF;
BUFF++;
}
if((strcmp(temp, ".make")==0) && (state_flag == 1)){ //방만들기 에러
printf("방 접속시에는 방을 만들 수 없습니다.\n");
return 1;
}
else if((strcmp(temp, ".join")==0) && (state_flag ==1)){ //방조인 에러
printf("방 접속시에는 다른 방에 접속 할 수 없습니다.\n");
return 1;
}
else if((strcmp(temp, ".quit")==0) && (state_flag == 0)){ //방나가기 에러
printf("대기실에서는 방에서 나갈 수 없습니다.\n");
return 1;
}
else if(strcmp(temp, ".help")==0){ //명령어 출력
printf("################################################\n");
printf("## 방만들기 : .make 방제목 ##\n");
printf("## 방들어가기 : .join 방번호 ##\n");
printf("## 방나가기 : .quit ##\n");
printf("## 접속종료 : .exit ##\n");
printf("## 사용자현황 : .show ##\n");
printf("## 명령어출력 : .help ##\n");
printf("## 귓속말 : .talk 상대방이름 포트번호 ##\n");
printf("################################################\n");
return 3;
}
else if((strcmp(temp, ".quit")==0) && (state_flag == 0)){ //접속 종료
return 2;
}
else if((strcmp(temp, ".make")==0) || (strcmp(temp, ".join")==0)){ //보통 명령어(대기실 -> 방안)
return 4;
}
else if((strcmp(temp, ".quit")==0)){ //보통 명령어(방안 -> 대기실)
return 5;
}
else if((strcmp(temp, ".show")==0)){ //보통 명령어(위치 변동 없음)
return 6;
}
else if((strcmp(temp, ".talk")==0)){
return 7;
}
return 0;
}
int multi_exit(char *BUFF){
char temp[5];
int i;
for(i = 0; i < 5; i++){
temp[i] = *BUFF;
BUFF++;
}
if(strcmp(temp, ".exit")==0) //멀티채팅 종료
return 1;
return 0;
}
void * thread_process(void * sockfd)
{
struct sockaddr_in recv_user_addr;
char recv_data[1024] = {0};
int recv_result;
int addrsize;
addrsize = sizeof(struct sockaddr_in);
while(1)
{
memset(recv_data, '\0', sizeof(recv_data));
recv_result = recvfrom((int)sockfd, recv_data, sizeof(recv_data), 0, (struct sockaddr*)&recv_user_addr, &addrsize);
if (recv_result <= 0)
continue;
printf("*From=>%s\n", recv_data);
}
}
int msg_conf(char *BUFF){
char temp[6];
int i;
for(i = 0; i < 6; i++){
temp[i] = *BUFF;
BUFF++;
}
if(strcmp(temp, ".multi")==0) //1:1채팅 메시지 일경우
return 1;
return 0;
}Forums:


gdb로 디버깅
gdb로 디버깅 해보세요.
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
댓글 달기