TCP 소켓 서버 Accept 부분 질문입니다.
글쓴이: l595659 / 작성시간: 금, 2022/07/08 - 5:48오후
MFC로 만든 소켓 서버 및 클라이언트 프로그램을 Class 화 하여 바꿔보고 테스트 해보고있습니다.
처음엔 acccept / recv 까진 잘 되다가 다음 메세지를 보내려고 해도 accept에서 멈춰있네요
accept에서 건드려보면 accept에서 안멈추고 recv로 넘어가서 다른클라이언트가 못들어가구요
어떻게 수정해야할지 감이 안잡히네요..
MFC에다가 적용하기전에 콘솔로 해보는 중인데 문제가 많네요..
헤더파일 입니다.
#pragma once #include "Winsock.h" #include <stdio.h> #include <vector> #include <atlstr.h> #pragma comment(lib, "ws2_32.lib") #define MAX_CLIENT_NUM 255 #define _CRT_SECURE_NO_WARNINGS #define BUFSIZE 255 #define BUFFER_SIZE 255 class TCPServer { public: TCPServer(); ~TCPServer(); struct UserData { char Ip_Address[16]; char port[10]; char strConnTime[30]; //DB에 보낼 접속시간 변수 char strCloseTime[30]; }; UserData m_user_list[MAX_CLIENT_NUM + 1]; SOCKET server_sock; //샘플 SOCKADDR_IN serv_socketAddr; //샘플 SOCKET clnt_sock; SOCKADDR_IN clnt_socketAddr; //---------------------------------------------------// CString slniPath; TCHAR ServerPort[MAX_PATH]; TCHAR ClientCount[MAX_PATH]; int index; int ServerPort_Num; int ClientCount_Num; int size; //--------recv 관련---------// char readbuffer[BUFSIZE]; int recvsize; CString strRecvTime; CString strMsg; //--------------------------// std::vector<SOCKET> client_list; std::vector<SOCKADDR_IN> udpClient_list; //---------------------------------------------------// void socketAndAddrInit(SOCKET servSock, SOCKADDR_IN serv_sockAddr, SOCKET clntSock, SOCKADDR_IN clnt_sockAddr); //다른곳의 socket 등을 header 파일 안의 소켓으로 void portClntCountInfo(CString iniLocation, CString serverSection, CString portKey, CString clientNumKey); //ini 파일 내용 가져오기 int winsockInit(); void serverSocket(int domain, int type, int protocol); void servSockAddr(int domain); int beforeAccept(); void clntSockAddr(int domain); int clntAccept(); void multiClient(); //---------------------------------------------------// void servRecvfrom(); void servSendto(); }; void TCPServer::socketAndAddrInit(SOCKET servSock, SOCKADDR_IN serv_sockAddr, SOCKET clntSock, SOCKADDR_IN clnt_sockAddr) { servSock = server_sock; serv_sockAddr = serv_socketAddr; clntSock = clnt_sock; clnt_sockAddr = clnt_socketAddr; } void TCPServer::portClntCountInfo(CString iniLocation, CString serverSection, CString portKey, CString clientNumKey) { //CString section; slniPath.Format(iniLocation); GetPrivateProfileString(serverSection, portKey, _T(""), ServerPort, MAX_PATH, slniPath); ServerPort_Num = _ttoi(ServerPort); GetPrivateProfileString(serverSection, clientNumKey, _T(""), ClientCount, MAX_PATH, slniPath); ClientCount_Num = _ttoi(ClientCount); } int TCPServer::winsockInit() { WSADATA wsaData; if (int retval = WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) printf("winsockInit() Error"); return 0; } void TCPServer::serverSocket(int domain, int type, int protocol) { server_sock = socket(domain, type, protocol); if (server_sock == SOCKET_ERROR) { printf("ServerSocket() Error"); } } void TCPServer::servSockAddr(int domain) { serv_socketAddr = { 0 }; serv_socketAddr.sin_family = domain; serv_socketAddr.sin_port = htons(ServerPort_Num); serv_socketAddr.sin_addr.s_addr = htonl(INADDR_ANY); } int TCPServer::beforeAccept() { int retval = bind(server_sock, (SOCKADDR*)&serv_socketAddr, sizeof(SOCKADDR)); if (retval == SOCKET_ERROR) { //printf("ServerBind() Error"); return 0; } listen(server_sock, ClientCount_Num); } void TCPServer::clntSockAddr(int domain) { clnt_socketAddr = { 0 }; clnt_socketAddr.sin_family = domain; clnt_socketAddr.sin_port = htons(ServerPort_Num); clnt_socketAddr.sin_addr.s_addr = htonl(INADDR_ANY); size = sizeof(SOCKADDR_IN); } int TCPServer::clntAccept() { clnt_sock = accept(server_sock, (SOCKADDR*)&clnt_socketAddr, &size); if (clnt_sock == SOCKET_ERROR) { printf("clntAccept() Error"); return 0; } } //-------------------ACCEPt------------------- //-------------------수정 필요------------------ void TCPServer::multiClient() { client_list.push_back(clnt_sock); strcpy_s(m_user_list<ol> </ol> .Ip_Address, inet_ntoa(clnt_socketAddr.sin_addr)); } void TCPServer::servRecvfrom() { recvsize = recv(clnt_sock, readbuffer, BUFSIZE, 0); readbuffer[recvsize] = '\0'; strMsg = CString(readbuffer, recvsize); printf("%s", strMsg); strMsg = ""; } void TCPServer::servSendto() { for (int i = 0; i < client_list.size(); i++) { } }
CPP 파일 입니다.
// ServerClass.cpp : 이 파일에는 'main' 함수가 포함됩니다. 거기서 프로그램 실행이 시작되고 종료됩니다. // #include <iostream> #include "ServerClass.h" TCPServer::TCPServer() {}; TCPServer::~TCPServer() {}; SOCKET server_socket; //샘플 SOCKADDR_IN servSocketAddr; //샘플 SOCKET clnt_socket; SOCKADDR_IN clntSocketAddr; int main() { TCPServer tcpserver; tcpserver.socketAndAddrInit(server_socket, servSocketAddr, clnt_socket, clntSocketAddr); tcpserver.portClntCountInfo(_T("./NetworkPath.ini"), _T("ServerInfo"), _T("Port"), _T("ClientCount")); tcpserver.winsockInit(); tcpserver.serverSocket(AF_INET, SOCK_STREAM, 0); tcpserver.servSockAddr(AF_INET); tcpserver.beforeAccept(); while (1) { #if 1 tcpserver.clntSockAddr(AF_INET); #endif tcpserver.clntAccept(); if (tcpserver.clnt_sock == SOCKET_ERROR) { break; } tcpserver.multiClient(); tcpserver.index++; //--------------------------------- tcpserver.servRecvfrom(); if (tcpserver.recvsize <= 0) { break; } } }
Forums:
accept()는 새로운 클라이언트가 접속할 때까지
accept()는 새로운 클라이언트가 접속할 때까지 대기하는 함수입니다만...
살펴보니 "tcp" server를 구현하시려고 하는
살펴보니 "tcp" server를 구현하시려고 하는 것으로 보이고 multiple clients 연결을 지원해야 하시려고 보네요.
주제넘게 조언을 드리자면 현재의 구조로는 하나의 client만 처리할 수 있습니다. UDP와 TCP는 다르기 때문에 이전 그대로 개념을 가져오면 안됩니다.
multiple clients를 지원하는 tcp server는 크게 fork()를 쓰는 것과 select()를 사용하는 방법으로 구분할 수 있습니다. 이 방법은 서로간에 큰 차이가 있으니 꼭 구글링을 통해 공부를 하시고 서버 구조를 설계해 보세요.
가장 좋은 방법은 아마 select를 사용하는 인터넷 예제를 완벽히 이해하고 진행하는 것일 겁니다.
구글링 해봐야겠네요
select를 사용하는것으로 찾아봐야겠네요
MFC로 만들때는 다중ㅈ 클라이언트가 되었는데 class 화 시켜서 하니까 하나의 클라이언트만 처리하길래 뭔가 했네요
댓글 달기