사용된 개념 공부하기
소켓 통신 및 IRC에 대해서 이해하기
struct Count {
std::size_t strong;
std::size_t weak;
}
template<typename T>
class Shared_ptr {
private:
Count *count;
T *type;
public:
~Shared_ptr() {
if (Count != NULL) {
Count->strong--;
if (Count->strong == 0) {
delete type;
if (Count->weak == 0) {
delete Count;
}
}
}
else
return ;
}
}

IRC : Internet Relay Chat의 약자로, 널리 사용되던 서버/클라이언트 통신을 이용한 채팅 프로토콜

서버 - 클라이언트의 관계를 그림으로 나타내면 위와 같이 그릴 수 있다.
보통 TCP/IP통신 프로토콜을 통해서 구현을 한다.
TCP/IP통신 프로토콜 중, IPv4 프로토콜은 아래의 그림과 같이 소켓이 구성되어 있다.

(출처 : 위키피디아)
총 32비트로 구성되어있으며, 4개의 계층으로 구성된 것이 TCP/IP의 IPv4 프로토콜이다.
4개의 계층 : 네트워크 접근 계층 -> 인터넷 계층 -> 전송 계층 -> 응용 계층
간단하게 말하면, IRC는 TCP/IP 프로토콜을 통해서 데이터를 송수신하여 통신을 할 수 있는 프로토콜
클라이언트 -> 서버 통신 시, 명령어 파라미터의 형식으로 메세지가 구성
서버 -> 클라이언트 통신 시, 해당 명령어에 맞는 형식으로 메세지를 전송해야함(해당 패킷이 일치하지 않을 경우, 동작하지 않음)
irssi v1.4.5기준
기본적으로 구현해야할 명령어 목록
KICK [paramter] : 해당 채널에서 parameter에 해당하는 유저 추방
TOPIC [parameter] : 해당 채널의 주제를 변경
MODE [mode][parameter] : 해당 채널의 주제를 변경
INVITE [parameter] : 해당 채널에 파라미터에 대한 접근권한 부여
PRIVMSG [user][parameter] : 메세지 전송 명령어
PING - 서버<->클라이언트가 연결이 정상적인지 일정 시간마다 확인하는 명령어, 클라이언트 -> 서버가 PING을 보내며, 서버 -> 클라이언트는 PONG을 보내야함
JOIN [parameter][password] : 원하는 채널에 접속
PASS [parameter] : 처음 서버 접속 시, 해당 채널의 패스워드가 있는지 확인하는 부분
NICK [parameter] : 닉네임 설정
USER [parameter][parameter] [parameter] :[parameter] : 처음 서버 접속 시, 발생하는 명령어로 RFC1459를 확인해보면 됨

int socket(int domain, int type, int protocol)
ex)
int server_s = socket(PF_INET, SOCK_STREAM, 0);
if (server_s == -1)
{
std::cout << "Fail to create socket\n";
}
Bind함수 : 인자로 받은 소켓에 주소를 할당해주는 함수
sockaddr 구조체
struct sockaddr_in
{
sa_family_t sin_family; /* Address family */
unsigned short int sin_port /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of ´struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
int bind(int socketfd, struct sockaddr *myaddr, socklen_t addrlen)
ex)
struct sockaddr_in server_a;
memset( &server_addr, 0, sizeof( server_addr);
// IPv4 인터넷 프로토롤
server_a.sin_family = PF_INET;
// 사용할 port 번호는 4000
// sin_port에 인터넷 프로토콜에 맞게 끔 비트를 수정해야하는데
// 그 역할을 해주는 함수 -> htons
server_a.sin_port = htons(포트번호);
// 32bit IPV4 주소
server_a.sin_addr.s_addr = htonl(주소);
if(bind(server_s, reinterpert_cast<sockaddr*>(server_a), sizeof(server_a)))
{
std::cout << "Fail to create socket\n";
exit(1);
}
int listen(int sock, int backlog)
ex)
if (listen(server_s, 5) == -1)
{
std::cout << "Listen Error";
exit(1);
}
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
ex)
sockaddr_in info;
socklen_t size = sizeof(info);
int client_s;
socket = ::accept(this->socket, reinterpret_cast<sockaddr *>(&info), &size);
if (socket == -1)
{
std::cout << "Fail to accept socket";
exit(1);
}