WSADATA wsa;
int code = WSAStartup(MAKEWORD(2, 2), &wsa);
if (!code) {
server_init();
std::thread th1[MAX_CLIENT];
for (int i = 0; i < MAX_CLIENT; i++) { // 인원 수 만큼 thread 생성해서 각각의 클라이언트가 동시에 소통할 수 있도록 함.
th1[i] = std::thread(add_client);
}
while (1) { // 무한 반복문을 사용하여 서버가 계속해서 채팅 보낼 수 있는 상태를 만들어 줌. 반복문을 사용하지 않으면 한 번만 보낼 수 있음.
string text, msg = "";
std::getline(cin, text);
const char* buf = text.c_str();
msg = server_sock.user + " : " + buf;
send_msg(msg.c_str()); // 서버가 보내는 메세지
}
for (int i = 0; i < MAX_CLIENT; i++) {
th1[i].join();
//thread 작업이 끝날 때까지 main 함수가 끝나지 않도록 해줌.
}
closesocket(server_sock.sck);
}
else {
cout << "프로그램 종료. (Error code : " << code << ")";
}
WSACleanup();
return 0;
server_sock.sck = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN server_addr = {}; // 소켓 주소 설정 변수
server_addr.sin_family = AF_INET; // 소켓은 Internet 타입
server_addr.sin_port = htons(7777); // 서버 포트 설정
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Any인 경우는 호스트를 127.0.0.1로 잡아도 되고 localhost로 잡아도 되고 양쪽 다 허용하게 할 수 있다. 그것이 INADDR_ANY이다.
bind(server_sock.sck, (sockaddr*)&server_addr, sizeof(server_addr)); // 설정된 소켓 정보를 소켓에 바인딩한다.
listen(server_sock.sck, SOMAXCONN); // 소켓을 대기 상태로 기다린다.
server_sock.user = "server";
cout << "Server On" << endl;
SOCKADDR_IN addr = {};
int addrsize = sizeof(addr);
char buf[MAX_SIZE] = { };
ZeroMemory(&addr, addrsize); // addr의 메모리 영역을 0으로 초기화
SOCKET_INFO new_client = {};
new_client.sck = accept(server_sock.sck, (sockaddr*)&addr, &addrsize);
recv(new_client.sck, buf, MAX_SIZE, 0); // Winsock2의 recv 함수. client가 보낸 닉네임을 받음.
new_client.user = string(buf);
string msg = "[공지] " + new_client.user + " 님이 입장했습니다.";
cout << msg << endl;
sck_list.push_back(new_client); // client 정보를 담는 sck_list 배열에 새로운 client 추가
std::thread th(recv_msg, client_count); // 다른 사람들로부터 오는 메시지를 계속해서 받을 수 있는 상태로 만들어 두기.
client_count++; // client 수 증가.
cout << "[공지] 현재 접속자 수 : " << client_count << "명" << endl;
send_msg(msg.c_str()); // c_str : string 타입을 const chqr* 타입으로 바꿔줌.
th.join();
for (int i = 0; i < client_count; i++) {
send(sck_list[i].sck, msg, MAX_SIZE, 0);
}
try {
driver = sql::mysql::get_mysql_driver_instance();
con = driver->connect(server, username, password);
}
catch (sql::SQLException& e) {
cout << "Could not connect to server. Error message: " << e.what() << endl;
exit(1);
}
// 데이터베이스 선택
con->setSchema("chattingproject");
// db 한글 저장을 위한 셋팅
stmt = con->createStatement();
stmt->execute("set names euckr");
if (stmt) { delete stmt; stmt = nullptr; }
char buf[MAX_SIZE] = { };
string msg = "";
while (1) {
ZeroMemory(&buf, MAX_SIZE);
if (recv(sck_list[idx].sck, buf, MAX_SIZE, 0) > 0) { // 오류가 발생하지 않으면 recv는 수신된 바이트 수를 반환. 0보다 크다는 것은 메시지가 왔다는 것.
string sbuf(buf);
if (sbuf.compare("#") == 0)
show_func(idx);
else if (sbuf.compare("#USER") == 0)
show_user(idx);
else if (buf[0] == '#') {
int cur_position = 0;
int position = sbuf.find(" ", cur_position);
int len = position - cur_position;
string flag = sbuf.substr(cur_position, len);
if (flag.compare("#DM") == 0)
send_dm(position, sbuf, idx);
else if (flag.compare("#CAL") == 0)
calculator(idx, position, sbuf);
}
else {
msg = sck_list[idx].user + " : " + buf;
pstmt = con->prepareStatement("INSERT INTO chatting(sender, message) VALUES(?,?)"); // INSERT
pstmt->setString(1, sck_list[idx].user);
pstmt->setString(2, buf);
pstmt->execute(); // 쿼리 실행
pstmt = con->prepareStatement("SELECT date_format(time, '%H:%m') FROM chatting ORDER BY time DESC LIMIT 1");
result = pstmt->executeQuery();
while (result->next()) {
msg += " [" + result->getString(1) + "]\n";
}
cout << msg << endl;
send_msg(msg.c_str());
}
}
else { //그렇지 않을 경우 퇴장에 대한 신호로 생각하여 퇴장 메시지 전송
msg = "[공지] " + sck_list[idx].user + " 님이 퇴장했습니다.";
cout << msg << endl;
send_msg(msg.c_str());
del_client(idx); // 클라이언트 삭제
return;
}
}
closesocket(sck_list[idx].sck);
sck_list.erase(sck_list.begin() + idx);
client_count--;
string msg =
"--------------------------------------------------\n"
"* # : FUNC LIST *\n"
"* #USER :현재 접속중인 사용자 아이디 *\n"
"* #DM receiver message : DM 보내기 *\n"
"* #CAL number operator number : 사칙연산 *\n"
"* #GAME : UP & DOWN 게임 *\n"
"* #EXIT : 프로그램 종료 *\n"
"--------------------------------------------------\n";
send(sck_list[idx].sck, msg.c_str(), MAX_SIZE, 0);
string msg = "현재 접속중인 사람 : ";
for (int i = 0; i < client_count; i++) {
msg += sck_list[i].user;
msg += " ";
}
send(sck_list[idx].sck, msg.c_str(), MAX_SIZE, 0);
int cur_position = position + 1;
position = sbuf.find(" ", cur_position);
int len = position - cur_position;
string receiver = sbuf.substr(cur_position, len);
cur_position = position + 1;
string dm = sbuf.substr(cur_position);
string msg = "[DM] " + sck_list[idx].user + " : " + dm;
pstmt = con->prepareStatement("INSERT INTO chatting(sender,receiver, message) VALUES(?,?,?)"); // INSERT
pstmt->setString(1, sck_list[idx].user);
pstmt->setString(2, receiver);
pstmt->setString(3, dm);
pstmt->execute(); // 쿼리 실행
pstmt = con->prepareStatement("SELECT date_format(time, '%H:%m') FROM chatting ORDER BY time DESC LIMIT 1");
result = pstmt->executeQuery();
while (result->next()) {
msg += " [" + result->getString(1) + "]\n";
}
cout << msg << endl;
for (int i = 0; i < client_count; i++) {
if (receiver.compare(sck_list[i].user) == 0)
send(sck_list[i].sck, msg.c_str(), MAX_SIZE, 0);
}
int cur_position = position + 1;
position = sbuf.find(" ", cur_position);
int len = position - cur_position;
string num1 = sbuf.substr(cur_position, len);
cur_position = position + 1;
position = sbuf.find(" ", cur_position);
string op = sbuf.substr(cur_position, 1);
cur_position = position + 1;
string num2 = sbuf.substr(cur_position);
double result = 0;
if (op == "+")
result = std::stoi(num1) + std::stoi(num2);
else if (op == "-")
result = std::stoi(num1) - std::stoi(num2);
else if (op == "*")
result = std::stoi(num1) * std::stoi(num2);
else if (op == "/")
result = (double)std::stoi(num1) / std::stoi(num2);
string res = std::to_string(result);
string msg = "[RESULT] " + num1 + " " + op + " " + num2 + " = " + res;
cout << msg << endl;
send(sck_list[idx].sck, msg.c_str(), MAX_SIZE, 0);
콘솔 채팅방 크기, 이름 설정
system("mode con: cols=50 lines=40 | title CodingOnTalk");
string title = "title CodingOnTalk - " + user_name;
Sleep(1000);
system("cls");
system("color 60");
system(title.c_str());
void textcolor(int foreground, int background)
{
int color = foreground + background * 16;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
textcolor(0, 6); // 기본 (글씨 검정색, 배경 노란색)
textcolor(4,6); // 서버에서 온 메세지는 빨간색으로 출력
textcolor(1,6); // DM은 파란색으로 출력
char* pw = new char[20];
int i = 0;
while ((pw[i] = _getch()) != 13)
{
if (pw[i] == 8) // 백스페이스 입력
{
printf("\b");
cout << ' ';
printf("\b");
if (i > 0)
i--;
}
else
{
cout << '*';
i++;
}
}
pw[i] = '\0';
user_pw = pw;