C++ 소켓에서 고통 받고 있습니다.ㅠㅠㅠ 도와주실 분 있으신가요(코드 태그 달았습니다!)
선 질문입니다.
1. 서버/클라이언트 구조를 만들려고 합니다. 만약에 둘 중 하나에서 Send를 했 다른 하나에서 recv를 걸었으나 2개 이상의 Send Recv 구조에선 각 Send하고 Recv가 어디에 걸리는지 모르겠습니다...ㅠㅠ
예를 들어
Send(1)
Recv(1)
Send(2)
Recv(2)
라면 1은 1에만 걸리고 2는 2에만 걸리는 건가요?
각 서버와 노드에서 코드를 읽는 속도가 다를 것 같은데, 그렇게 되면 한쪽에서 먼저 Send(2)까지 읽어버리고 쏴주면 Recv(1)은 Send(2)를 받는게 아닌가 해서요.. ㅠㅠ
2. 아래 코드에서 중간 두 부분부터 먹통이 되길래 계속 자료형 바꿔가면서 테스트를 해보았는데... (6시간넘게..)
아래 printf를 붙여서 어디서 부터 먹통이 되는지 체크하는 방법은 터득했는데.. 정작 문제가 해결이 안 됩니다.ㅠㅠ
----------------------------------------------------------
printf("\n1"); ret = send(*(SOCKET*)ns, welcome, MAX_BUFFER, 0); printf("\n2");
--------------------------------------------------------
이 부분에서 welcome이 서버에서 제대로 송신은 된 것 같은데, 클라이언트 단에서는 출력이 안 됩니다.
--------------------------------------------------------
while (1); { printf("\n3"); recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); printf("클라이언트의 ID는 %s 이다.)\n", messageBuffer); WaitForSingleObject(hMutex, INFINITE);//뮤텍스 실행 strcpy(IDlist[IDcount], messageBuffer); printf("ID는 %s", IDlist[IDcount]); IDcount++; ReleaseMutex(hMutex);//뮤텍스 중지 printf("\n4"); memset(&messageBuffer, 0, sizeof(messageBuffer)); _itoa_s(IDcount, messageBuffer, 10); send(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); printf("\n5"); }
--------------------------------------------------------
이 부분은 아예 진입을 못해서 goto문으로 while문 안으로 넣어줘도 애가 움직일 생각을 안 합니다.ㅠㅠ 1,2 까지는 출력이 되는데 3부터는 아예 됩니다...
같은 문제로 2일째 고심중입니다.. 고수님들의 도움 부탁드립니다.
----서버 코드 #include "stdafx.h" #include <stdio.h> #include <winsock2.h> #include <stdlib.h> #include <process.h> #include <Windows.h> #pragma comment(lib, "Ws2_32.lib") #pragma warning(disable:4996) #define MAX_BUFFER 1024 #define SERVER_PORT 9001 #define Max_socket 5 SOCKET Clientlist[Max_socket]; //최대 5개까지 void makeThread(void *data); int clientCount; char welcome_ok[] = "접속을 환영한다."; char IDlist[Max_socket][MAX_BUFFER]; int client_num; int addrLen; int IDcount = 0; int recv_id[]; int clientSocket[MAX_BUFFER]; int i, j; HANDLE hMutex;//뮤텍스 void makeThread(void *ns) { WaitForSingleObject(hMutex, INFINITE); clientCount++; client_num++; printf("(슬롯 %d개 남음)\n", Max_socket - clientCount); // 갯수로 판단 ReleaseMutex(hMutex); // 5-1. 데이터 읽기 char welcome[100] = { 0}; char messageBuffer[MAX_BUFFER] = { 0 }; double num1 = 0, num2 = 0; double result = 0; int ret; printf("\n1"); ret = send(*(SOCKET*)ns, welcome, MAX_BUFFER, 0); printf("\n2"); goto in; while (1); { in: printf("\n3"); recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); printf("클라이언트의 ID는 %s 이다.)\n", messageBuffer); WaitForSingleObject(hMutex, INFINITE);//뮤텍스 실행 strcpy(IDlist[IDcount], messageBuffer); printf("ID는 %s", IDlist[IDcount]); IDcount++; ReleaseMutex(hMutex);//뮤텍스 중지 printf("\n4"); memset(&messageBuffer, 0, sizeof(messageBuffer)); _itoa_s(IDcount, messageBuffer, 10); send(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); printf("\n5"); for (i = 0; i < Max_socket; i++) { memset(&messageBuffer, 0, sizeof(messageBuffer)); strcpy(messageBuffer, IDlist[i]); send(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); } printf("\n5"); } // 5-2.사칙연산, 종료 while (1) { recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); if ((messageBuffer[0] == '+' || messageBuffer[0] == '-' || messageBuffer[0] == '/' || messageBuffer[0] == '*' || messageBuffer[0] == 'q') != 1) { //printf("바르게 입력바랍니다.\n"); memset(&messageBuffer, 0, sizeof(messageBuffer)); strcpy(messageBuffer, "incorrect command"); send(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); continue; } if (messageBuffer[0] == '+') { printf("뎃섬을 하는군\n "); memset(&messageBuffer, 0, sizeof(messageBuffer)); //숫자 1 받음 recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); num1 = atof(messageBuffer); printf("숫자1은 %f이다\n", num1); // 숫자로 변환 memset(&messageBuffer, 0, sizeof(messageBuffer)); recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); num2 = atof(messageBuffer); printf("숫자2은 %f 이다\n", num2); // 숫자로 변환 result = num1 + num2; memset(&messageBuffer, 0, sizeof(messageBuffer)); sprintf(messageBuffer, "%f", result); send(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); } if (messageBuffer[0] == '-') { printf("뺄셈을 하는군\n"); memset(&messageBuffer, 0, sizeof(messageBuffer)); //숫자 1 받음 recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); num1 = atof(messageBuffer); printf("숫자1은 %f이다\n", num1); // 숫자로 변환 memset(&messageBuffer, 0, sizeof(messageBuffer)); recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); num2 = atof(messageBuffer); printf("숫자2은 %f 이다\n", num2); // 숫자로 변환 result = num1 - num2; memset(&messageBuffer, 0, sizeof(messageBuffer)); sprintf(messageBuffer, "%f", result); send(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); } if (messageBuffer[0] == '*') { printf("곱센\n"); memset(&messageBuffer, 0, sizeof(messageBuffer)); //숫자 1 받음 recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); num1 = atof(messageBuffer); printf("숫자1은 %f이다\n", num1); // 숫자로 변환 memset(&messageBuffer, 0, sizeof(messageBuffer)); recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); num2 = atof(messageBuffer); printf("숫자2은 %f 이다\n", num2); // 숫자로 변환 result = num1 * num2; memset(&messageBuffer, 0, sizeof(messageBuffer)); sprintf(messageBuffer, "%f", result); send(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); } if (messageBuffer[0] == '/') { printf("나눗셈\n"); memset(&messageBuffer, 0, sizeof(messageBuffer)); //숫자 1 받음 recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); num1 = atof(messageBuffer); printf("숫자1은 %f이다\n", num1); // 숫자로 변환 memset(&messageBuffer, 0, sizeof(messageBuffer)); recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); num2 = atof(messageBuffer); printf("숫자2은 %f 이다\n", num2); // 숫자로 변환 result = num1 / num2; memset(&messageBuffer, 0, sizeof(messageBuffer)); sprintf(messageBuffer, "%f", result); send(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); } if (messageBuffer[0] == 'q') //사칙연산 나가기 { memset(&messageBuffer, 0, sizeof(messageBuffer)); recv(*(SOCKET*)ns, messageBuffer, MAX_BUFFER, 0); WaitForSingleObject(hMutex, INFINITE);//뮤텍스 실행 for (i = 0; i < Max_socket; i++) //배열의 갯수만큼 { if (IDlist[i][MAX_BUFFER] == messageBuffer[0]) //만약 현재 clientSock값이 배열의 값과 같다면 { IDlist[i][MAX_BUFFER] = '0'; break; } } for (i = 0; i = Max_socket; i++) { if (IDlist[i][MAX_BUFFER] = '0') j = i; } for (i = j; i = Max_socket; i++) { IDlist[i][MAX_BUFFER] = IDlist[i + 1][MAX_BUFFER]; } clientCount--;//클라이언트 개수 하나 감소 IDcount--; printf("클라이언트 해제\n슬롯 %d개 남음\n", Max_socket - clientCount); ReleaseMutex(hMutex);//뮤텍스 중지 break; } printf("나왔당!!! !룰룰"); } closesocket(*(SOCKET*)ns); //연결된 클라이언트 정렬및 재정비하기. printf("끝"); } int main(void) { hMutex = CreateMutex(NULL, FALSE, NULL); WSADATA WSAData; if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) { printf("Error - Can not load 'winsock.dll' file\n"); return -1; } // 1. 소켓생성 SOCKADDR_IN serverAddr, clientAddr; SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listenSocket == INVALID_SOCKET) { printf("Error - Invalid socket\n"); return -1; } printf("socket Created\n\n"); // 서버정보 객체설정 serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(SERVER_PORT); serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 2. 소켓설정 if (bind(listenSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { printf("Error - Fail bind\n"); closesocket(listenSocket); // Winsock End WSACleanup(); return -1; } printf("binding success...\n\n"); // 3. 수신대기열생성 if (listen(listenSocket, 5) == SOCKET_ERROR) { printf("Error - Fail listen\n"); closesocket(listenSocket); WSACleanup(); return -1; } printf("on listening...\n\n"); // 연결대기 정보변수 선언 addrLen = sizeof(clientAddr); // thread Handle 선언 while (1) { // 4. 연결대기 클라이언트소켓주소 배열에 저장 clientSocket[client_num] = accept(listenSocket, (struct sockaddr *)&clientAddr, &addrLen); _beginthread(makeThread, 0, &clientSocket[client_num]); printf("클라이언트 %s:%d 에서 접속", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port)); } // 6-2. 리슨 소켓종료 closesocket(listenSocket); WSACleanup(); getchar(); getchar(); return 0; }
클라이언트 코드
#include "stdafx.h" #include <winsock2.h> #include <stdlib.h> #include <windows.h> #include <process.h> #include <time.h> #pragma comment(lib, "Ws2_32.lib") #pragma warning(disable:4996) #define MAX_BUFFER 1024 #define SERVER_IP "127.0.0.1" #define SERVER_PORT 9001 void recv_thread(void* pData); int count; int listenSocket; int ret; char self_id[MAX_BUFFER]; int i, bufferLen; int main(void) { // Winsock Start - winsock.dll 로드 WSADATA WSAData; char messageBuffer[MAX_BUFFER]; if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) { printf("Error - Can not load 'winsock.dll' file\n"); return -1; } // 1. 소켓생성 SOCKADDR_IN serverAddr; listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listenSocket == INVALID_SOCKET) { printf("Error - Invalid socket\n"); closesocket(listenSocket); WSACleanup(); return -1; } // 서버정보 객체설정 serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP); serverAddr.sin_port = htons(SERVER_PORT); // 2. 연결요청 if (connect(listenSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { printf("Error - Fail to connect\n"); // 4. 소켓종료 closesocket(listenSocket); // Winsock End WSACleanup(); return -1; } printf("connect success\n\n"); ret = recv(listenSocket, messageBuffer, MAX_BUFFER, 0); printf("%s", messageBuffer); printf("Server Connected\n* 너의 ID가 무엇이냐? \n>"); scanf_s("%s", messageBuffer, sizeof(messageBuffer)); for (i = 0; i < MAX_BUFFER; i++) { self_id[i] = messageBuffer[i]; } bufferLen = strlen(messageBuffer); send(listenSocket, messageBuffer, bufferLen, 0); memset(&messageBuffer, 0, sizeof(messageBuffer)); recv(listenSocket, messageBuffer, MAX_BUFFER, 0); count = atoi(messageBuffer); for (i = 0; i < count; i++) { memset(&messageBuffer, 0, sizeof(messageBuffer)); recv(listenSocket, messageBuffer, MAX_BUFFER, 0); printf("현재 연결된 클라이언트 ID는 %s 이다.\n ", messageBuffer); printf("%d 번째 받음\n", i); } while (1) { printf("수행할 사칙연산은 무엇이냐?(+,-,/,* 중 입력,나가기 q)\n "); // 3-2. 연산자 보내기 memset(&messageBuffer, 0, sizeof(messageBuffer)); scanf_s("%s", messageBuffer, sizeof(messageBuffer)); if ((messageBuffer[0] == '+' || messageBuffer[0] == '-' || messageBuffer[0] == '/' || messageBuffer[0] == '*' || messageBuffer[0] == 'q') != 1) { send(listenSocket, messageBuffer, MAX_BUFFER, 0); //첫번째 연산자입력 memset(&messageBuffer, 0, sizeof(messageBuffer)); recv(listenSocket, messageBuffer, MAX_BUFFER, 0); printf("%s. \n", messageBuffer); continue; } if (messageBuffer[0] == 'q') { messageBuffer[1] = self_id[0]; send(listenSocket, messageBuffer, MAX_BUFFER, 0); break; } else { send(listenSocket, messageBuffer, MAX_BUFFER, 0); //첫번째 연산자입력 memset(&messageBuffer, 0, sizeof(messageBuffer)); printf("첫번째수를 입력하라\n"); scanf_s("%s", messageBuffer, sizeof(messageBuffer)); send(listenSocket, messageBuffer, MAX_BUFFER, 0);// 두번째 숫자 1 입력 memset(&messageBuffer, 0, sizeof(messageBuffer)); printf("두번째수를 입력하라\n"); scanf_s("%s", messageBuffer, sizeof(messageBuffer)); send(listenSocket, messageBuffer, MAX_BUFFER, 0);// 세번째 숫자 2 입력 memset(&messageBuffer, 0, sizeof(messageBuffer)); recv(listenSocket, messageBuffer, MAX_BUFFER, 0); printf("결과값은 %lf 이다.\n", atof(messageBuffer)); } printf("나왔다!!"); } // 4. 소켓종료 printf("서버와 연결이 끊겼습니다.\n"); closesocket(listenSocket); WSACleanup(); getchar(); getchar(); return 0; }
Remove semicolon
Remove semicolon
from
사랑합니다.
:)
댓글 달기