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
#include
#include
#include
#include
#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");
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");
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
#include
#include
#include
#include
#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;
}
Code tag
Use code tag please.
댓글 달기