안녕하세요. recv send 함수에 대한 질문드립니다.
글쓴이: K.I.D Neon (NK)... / 작성시간: 토, 2017/05/27 - 11:24오전
제가 pthread를 사용해서 간단한 채팅 프로그램 소스를 짰습니다.
그런데, 리눅스에서 send recv 함수를 사용해 쓰레드로 동기화 시켜 다음과 같이 구현했는데요.
Server Code
// Override
int User::run()
{
char buf[User::MAXSTRLEN];
while(true)
{
try
{
recvMessage(buf);
stringstream oss;
oss << "(" << getIP() << ":" << getPort() << ") : " << buf; // 익셉션 메시지 로그,,
sendMessageAll(oss.str().c_str()); // 모든 사용자에게 전달,,
cout << "(" << getIP() << ":" << getPort() << ") : " << buf << endl;
}
catch(ChatException ex)
{
stringstream oss;
oss << "(" << getIP() << ":" << getPort() << ") : " << "유저가 나갔습니다. ";
sendMessageAll(oss.str().c_str());
printLeaveUser(*this);
break; // 오류가 있으면, 서버가 종료.
}
}
pthread_mutex_lock(&App::pMutex);
int len = App::userList.size();
for(int i = 0; i < len; i++)
{
User *user = App::userList.at(i); // 사용자 목록에서 한 사용자를 가져옵니다,,
if(user->getSocket() == this->getSocket())
{
App::userList.erase(App::userList.begin() + i); // 사용자 리스트에서 끊어진 사용자 제거,,
break;
}
}
pthread_mutex_unlock(&App::pMutex);
delete this;
return 0;
}
void User::recvMessage(char *buf)
{
Message msg;
int len = 0;
memset(&msg, 0, sizeof(Message));
if(recv(this->recv_socket, (char*)&msg, sizeof(Message), 0) <= 0)
{
throw ChatException(SESSION_ERROR);
}
len = strnlen(msg.data, User::MAXSTRLEN);
strncpy(buf, msg.data, strnlen(msg.data, User::MAXSTRLEN));
buf[len] = 0;
}
void User::sendMessageAll(const char *buf)
{
int len = App::userList.size();
for(int i = 0; i < len; i++)
{
User *user = App::userList.at(i);
try
{
sendMessage(user->getSocket(), buf);
}
catch(ChatException ex)
{
throw ChatException(SEND_ERROR);
}
}
}
void User::sendMessage(int socket, const char *buf)
{
Message msg;
memset(&msg, 0, sizeof(Message));
if(buf != nullptr)
{
int len = strnlen(buf, User::MAXSTRLEN);
strncpy(msg.data, buf, len);
msg.data[len] = 0;
}
pthread_mutex_lock(&App::pMutex);
if(send(socket, (const char*)&msg, sizeof(Message), 0) <= 0)
{
pthread_mutex_unlock(&App::pMutex);
throw ChatException(SESSION_ERROR);
}
pthread_mutex_unlock(&App::pMutex);
}Client Code
int ChatClient::run()
{
// 보내고 받는 스레드를 각각 만들어줌,,
sendThread = new SendThread(this->client_socket);
recvThread = new RecvThread(this->client_socket);
connectServer(); // 서버 접속 시도...
sendThread->start();
recvThread->start();
sendThread->join(); // sendThread가 종료될 때까지 계속 대기..
recvThread->join();
return sendThread->getExitCode(); // 혹여 서버가 죽을 경우, 반환할 값 (join 함수에서 받아야 함)
}
void sendRecvInterface::recvMessage(int socket, char *buf)
{
Message msg;
int len = 0;
memset(&msg, 0, sizeof(Message));
if(recv(socket, (char*)&msg, sizeof(Message), 0) <= 0)
{
throw ChatException(1100);
}
len = strnlen(msg.data, ChatClient::MAXSTRLEN);
strncpy(buf, msg.data, len);
buf[len] = 0;
}
void sendRecvInterface::sendMessage(int socket, const char* buf)
{
Message msg;
memset(&msg, 0, sizeof(Message));
if(buf != nullptr)
{
int len = strnlen(buf, ChatClient::MAXSTRLEN);
strncpy(msg.data, buf, len);
msg.data[len] = 0;
}
pthread_mutex_lock(&App::pMutex);
if(send(socket, (const char*)&msg, sizeof(Message), 0) <= 0)
{
pthread_mutex_unlock(&App::pMutex);
throw ChatException(1100);
}
pthread_mutex_unlock(&App::pMutex);
}
void sendRecvInterface::gotoxy(int x, int y)
{
fprintf(stdout, "\033[%dd\033[%dG", y, x);
}
SendThread::SendThread(int cs) : client_socket(cs) {}
int SendThread::run()
{
int result = -1;
char buf[ChatClient::MAXSTRLEN];
while(true)
{
try
{
cin >> buf;
cin.clear();
if(exitUser(buf))
{
result = 0;
throw ChatException(2100);
}
sendMessage(this->client_socket, buf);
}
catch(ChatException ex)
{
close(this->client_socket);
break;
}
}
return result;
}
bool SendThread::exitUser(const char *buf)
{
if(strcmp(buf, UserCommand::EXIT) == 0)
{
return true;
}
return false;
}
RecvThread::RecvThread(int cs) {}
int RecvThread::run()
{
char buf[ChatClient::MAXSTRLEN];
while(true)
{
try
{
recvMessage(this->client_socket, buf);
cout << buf << endl;
}
catch (ChatException ex)
{
close(this->client_socket);
break;
}
}
return 0;
}이렇게 구현을해서, 클라이언트에서 cin >> buf 쪽에서 입력을 기다리고, 메시지를 입력하면, 서버로 보내는 간단한 채팅 프로그램입니다. 그런데, 메시지를 입력하고, 엔터를 누르면 한 개의 메시지만 가는게 아니라 해당 메시지가 여러 번 송신이 되는데, 왜 그런걸까요? 고수님들의 도움을 부탁드립니다.
Forums:


댓글 달기