C++ 소켓에서 고통 받고 있습니다.ㅠㅠㅠ 도와주실 분 있으신가요(코드 태그 달았습니다!)

aybabtu0974의 이미지

선 질문입니다.

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;
}

Guest의 이미지

Remove semicolon
from

while (1);
aybabtu0974의 이미지

:)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.