서버 코드
더보기
더보기
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <winsock2.h>
#include <list>
#include <string>
#pragma comment (lib, "ws2_32.lib")
//서버
struct User
{
SOCKET m_Sock;
SOCKADDR_IN m_Addr;
std::string m_csName;
short m_iPort;
void set(SOCKET sock, SOCKADDR_IN addr)
{
m_Sock = sock;
m_Addr = addr;
m_csName = inet_ntoa(addr.sin_addr);
m_iPort = ntohs(addr.sin_port);
}
};
void main()
{
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
return;
}
SOCKET ListenSock = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN sa;
ZeroMemory(&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(10000);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
int iRet = bind(ListenSock, (sockaddr*)&sa, sizeof(sa));
if (iRet == SOCKET_ERROR) return;
iRet = listen(ListenSock, SOMAXCONN);
if (iRet == SOCKET_ERROR) return;
SOCKADDR_IN clientAddr;
int iLen = sizeof(clientAddr);
std::cout
<< "서버 가동중......." << std::endl;
u_long on = 1;
ioctlsocket(ListenSock, FIONBIO, &on);
std::list<User> userlist;
while (1)
{
SOCKET clientSock = accept(ListenSock,
(sockaddr*)&clientAddr, &iLen);
if (clientSock == SOCKET_ERROR)
{
int iError = WSAGetLastError();
if (iError != WSAEWOULDBLOCK)
{
std::cout << "ErrorCode=" << iError << std::endl;
break;
}
}
else
{
User user;
user.set(clientSock, clientAddr);
userlist.push_back(user);
std::cout
<< "ip =" << inet_ntoa(clientAddr.sin_addr)
<< "port =" << ntohs(clientAddr.sin_port)
<< " " << std::endl;
u_long on = 1;
ioctlsocket(clientSock, FIONBIO, &on);
std::cout << userlist.size() << " 명 접속중.." << std::endl;
}
if (userlist.size() > 0)
{
std::list<User>::iterator iter;
for (iter = userlist.begin(); iter != userlist.end(); )
{
User user = *iter;
char szRecvBuffer[256] = { 0, };
int iRecvByte = recv(user.m_Sock, szRecvBuffer, 256, 0);
if (iRecvByte == 0)
{
closesocket(user.m_Sock);
iter = userlist.erase(iter);
std::cout << user.m_csName << " 접속종료됨." << std::endl;
continue;
}
if (iRecvByte == SOCKET_ERROR)
{
int iError = WSAGetLastError();
if (iError != WSAEWOULDBLOCK)
{
iter = userlist.erase(iter);
std::cout << user.m_csName << " 비정상 접속종료됨." << std::endl;
}
else
{
iter++;
}
}
else
{
std::list<User>::iterator iterSend;
for (iterSend = userlist.begin();
iterSend != userlist.end(); )
{
User user = *iterSend;
std::cout << szRecvBuffer << "받음" << std::endl;
int iSendByte = send(user.m_Sock, szRecvBuffer, iRecvByte, 0);
std::cout << user.m_Sock << ":" << iSendByte << "보냄." << std::endl;
if (iSendByte == SOCKET_ERROR)
{
int iError = WSAGetLastError();
if (iError != WSAEWOULDBLOCK)
{
closesocket(user.m_Sock);
iterSend = userlist.erase(iterSend);
std::cout << user.m_csName << " 비정상 접속종료됨." << std::endl;
}
}
else
{
iterSend++;
}
}
if (iter != userlist.end())
{
iter++;
}
}
}
}
}
closesocket(ListenSock);
WSACleanup();
}
클라이언트 코드
더보기
더보기
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <winsock2.h>
#include <conio.h>
#pragma comment (lib, "ws2_32.lib")
//클라이언트
void main()
{
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
return;
}
SOCKET sock = socket(AF_INET,
SOCK_STREAM, 0); //SOCK_STREAM, SOCK_DGRAM
//IPPROTO_TCP,IPPROTO_UDP
SOCKADDR_IN sa;
ZeroMemory(&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(10000);
sa.sin_addr.s_addr = inet_addr("ip");
int iRet = connect(
sock,
(sockaddr*)&sa,
sizeof(sa));
if (iRet == SOCKET_ERROR)
{
return;
}
std::cout << "접속성공!" << std::endl;
u_long on = 1;
ioctlsocket(sock, FIONBIO, &on);
char szBuffer[256] = { 0, };
int iEnd = 0;
while (1)
{
if (_kbhit() == 1)
{
int iValue = _getche();
if (iValue == '\r' && strlen(szBuffer) == 0)
{
break;
}
if (iValue == '\r')
{
int iSendByte = send(sock,
szBuffer,
iEnd,
0);
if (iSendByte == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
std::cout << "비정상 서버종료됨.." << std::endl;
}
}
iEnd = 0;
ZeroMemory(szBuffer, sizeof(char) * 256);
}
else
{
szBuffer[iEnd++] = iValue;
}
}
else
{
char szRecvBuffer[256] = { 0, };
int iRecvByte = recv(sock, szRecvBuffer, 256, 0);
if (iRecvByte == 0)
{
std::cout << "서버종료됨.." << std::endl;
break;
}
if (iRecvByte == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
std::cout << "비정상 서버종료됨.." << std::endl;
break;
}
}
else
{
std::cout << "\n" << szRecvBuffer;
ZeroMemory(szRecvBuffer, sizeof(char) * 256);
}
}
}
std::cout << "접속종료" << std::endl;
closesocket(sock);
WSACleanup();
}
'STUDY > Network Programming' 카테고리의 다른 글
Network Programming - 윈도우 메세지 통해 소켓 입출력, WSAAsyncSelect 모델 (11) | 2022.01.10 |
---|---|
Network Programming - 다중 입출력 함수 Select() (0) | 2022.01.07 |
Network Programming - 소켓모드의 Blocking & NonBlocking (0) | 2022.01.06 |
Network Programming - 쓰레드(Thread)와 프로세스(Process) , 클라이언트/서버 멀티쓰레드 C++ 채팅 프로그램 (0) | 2022.01.06 |
Network Programming - TCP/UDP 프로토콜 장단점, WinSock 윈속 소켓 (0) | 2021.12.31 |