TCP/IP 소켓프로그래밍 기초적인거 질문 받아주실 수 있나요?
글쓴이: 201413694 / 작성시간: 수, 2018/09/12 - 3:05오후
과제떄문에 TCP/IP소켓프로그래밍을 독학하게 되었습니다.
서버와 클라이언트에 대한 소스코드는 아래와 같습니다. 윈도우 운영체제에 C언어로 작성했어요
로컬호스트에서 제 아이피 또는 루프백을 이용해 cmd창 2개를 띄워서 실행하면 서버와 클라이언트 모두 잘 받았습니다.
그러나 과제의 핵심사항이 장비(회사에서 지급)와 PC를 연결해서
PC에서 장비로 패킷(A003A0030101000E)를 보내서 162바이트를 받는것입니다.
그러나 장비와 PC를 연결하면 소켓통신이 반응하지않습니다.
cmd를 쓸때 클라이언트응용프로그램 과 장비ip 및 포트를 넣었을떄 추가적인 메시지가 안뜹니다.
장비와 연결했을떄 핑은 나왔고
윈7에 알맞게 방화벽도 특정포트 허용했습니다.
답변부탁 드립니다.
//서버 순서:원속초기화-소켓생성-(데이터통신:bind,listen,accept)-소켓해제-원속종료
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define BUFSIZE 2018
void ErrorHandling(char* message);
int main(int argc, char *argv[])
{
char hex[] = "A003A0030101000E";
char *ptr;
long value;
value = strtoul(hex, &ptr, 16);
SOCKET sock, clientsock;
WSADATA wsa;
struct sockaddr_in sockinfo, clientinfo;
int clientsize;
char message[] = "TCP/IP 소켓 프로그래밍";
char buffer[BUFSIZE] = { 0 };
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
ErrorHandling("Winsock DLL 실패");
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
ErrorHandling("Soecket 생성 실패");
memset(&sockinfo, 0, sizeof(SOCKADDR_IN));
sockinfo.sin_family = AF_INET; //주소체계 AF_INET,AF_INET6,AF_LOCAL
sockinfo.sin_port = htons(argv[1]);
sockinfo.sin_addr.s_addr = htonl(INADDR_ANY); //ip를 지정함
if (bind(sock, (SOCKADDR*)&sockinfo, sizeof(sockinfo)) == SOCKET_ERROR)
ErrorHandling("bine 실패");
if (listen(sock, 5) == SOCKET_ERROR) //[성공시 0,실패시 SOCKET_ERROR]
ErrorHandling("listen 실패");
printf("클라이언트로부터 접속을 기다리고 있습니다...\n");
clientsize = sizeof(clientinfo);
clientsock = accept(sock, (SOCKADDR*)&clientinfo, &clientsize);
if (clientsock == INVALID_SOCKET) //소켓핸들값이라서 INVALID_SOCKET로 확인
ErrorHandling("accept 실패");
send(clientsock, message, sizeof(message), 0);
send(clientsock, hex, sizeof(hex), 0);
closesocket(sock);
closesocket(clientsock);
printf("성공\n");
WSACleanup();
}
void ErrorHandling(char *message) {
WSACleanup();
fputs(message, stderr);
fputc('\n', stderr);
_getch();
exit(1);
}------------------------------
//클라이언트 순서:초기화-소켓생성-connect-소켓해제-원속 종료
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define BUFSIZE 2048
void ErrorHandling(char *message);
int main(int argc, char *argv[])
{
char hex[] = "A003A0030101000E";
char *ptr;
long value;
value = strtoul(hex, &ptr, 16);
SOCKET clientsock;
WSADATA wsa;
struct sockaddr_in sockinfo;
char message[BUFSIZE];
int strlen;
if (argc != 3)
{
printf("Usage : %s <IP> <PORT> \n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
ErrorHandling("Winsock DLL 실패");
clientsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientsock == INVALID_SOCKET)
ErrorHandling("Soecket 생성 실패");
memset(&sockinfo, 0, sizeof(sockinfo));
sockinfo.sin_family = AF_INET;
sockinfo.sin_port = htons(atoi(argv[2]));
sockinfo.sin_addr.s_addr = inet_addr(argv[1]);
if (connect(clientsock, (SOCKADDR*)&sockinfo, sizeof(sockinfo)) == SOCKET_ERROR)
ErrorHandling("accept 실패");
strlen = recv(clientsock, message, sizeof(message) - 1, 0);
if (strlen == -1) // recv 함수 반환 값이 -1이면 메시지 수신 실패
ErrorHandling("message 실패");
strlen = recv(clientsock, hex, sizeof(hex) - 1, 0);
if(strlen == -1)
ErrorHandling("전송 오류");
printf("받은 데이터는 16진수로 0x%08X 입니다.\n", htons(strlen));
printf("받은 데이터는 십진수로 %d 입니다.\n", htons(strlen));
printf(" Server say: %s \n", message);
closesocket(clientsock);
WSACleanup();
}
void ErrorHandling(char *message) {
WSACleanup();
fputs(message, stderr);
fputc('\n', stderr);
_getch();
exit(1);
}Forums:


떄문에 ? 때문에 ?
떄문에 ? 때문에 ?
사소한 오타 때문에 질문의 핵심에서 답변이 멀어질 수 있어요.
kldp 에 소스코드 넣을 때는 아래 링크 참고하세요.
https://kldp.org/node/158191
세벌 https://sebuls.blogspot.kr/
감사합니다
감사합니다
wireshark로 실제 데이터가 왔다 갔다 하는지
wireshark로 실제 데이터가 왔다 갔다 하는지 확인해 보세요.
참고해보세요.
구름 IDE - 웹 컴파일러
https://www.goorm.io/
구름 IDE - 웹 컴파일러 사용방법
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=278&MAEULNO=20&no=32422&page=1
/* TCP/IP 소켓프로그래밍 기초적인거 질문 받아주실 수 있나요? https://kldp.org/node/160126 //winapi utf-8 ansi Windows API ANSI functions and UTF-8 https://stackoverflow.com/questions/8831143/windows-api-ansi-functions-and-utf-8 [WinAPi]WinAPI를 이용하여 cp949(ANSI) - utf8 인코딩 변환 C/C++ http://blog.naver.com/PostView.nhn?blogId=nimi315&logNo=50093464158 How to read text file of type utf-8 format,ANSI and Unicode in VC++ https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/00be67c0-59ca-4bbe-95f8-e89581a56309/how-to-read-text-file-of-type-utf8-formatansi-and-unicode-in-vc?forum=vclanguage Reading characters from UTF-8 Encoded File https://www.codeproject.com/Questions/311387/Reading-characters-from-UTF-8-Encoded-File.aspx recv winsock locale 언저 지역 설정 https://kldp.org/node/159457#comment-626326 */ //서버 순서:원속초기화-소켓생성-(데이터통신:bind,listen,accept)-소켓해제-원속종료 #include <stdio.h> #include <stdlib.h> #include <winsock2.h> #include <windows.h> #include <iostream> #include <string> #include <conio.h> //Error: ‘Getch’ Was Not Declared In This Scope //https://www.dreamincode.net/forums/topic/341445-error-getch-was-not-declared-in-this-scope/ //htons function //https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-htons //WinSock32 //https://social.msdn.microsoft.com/Forums/vstudio/en-US/82ee2e1b-9957-4147-ac31-4e9ac82cbd59/winsock32?forum=vcgeneral #include <locale.h> #pragma comment(lib,"ws2_32.lib") #define BUFSIZE 2018 void ErrorHandling(char* message); using namespace std; //[WinAPi]WinAPI를 이용하여 cp949(ANSI) - utf8 인코딩 변환 C/C++ //http://blog.naver.com/PostView.nhn?blogId=nimi315&logNo=50093464158 //UTF-8 을 ANSI 로 변환 (한글 출력에 사용) string utf8_to_ansi(string &utf8) { WCHAR unicode[1500]; char ansi[1500]; memset(unicode, 0, sizeof(unicode)); memset(ansi, 0, sizeof(ansi)); ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, unicode, sizeof(unicode)); ::WideCharToMultiByte(CP_ACP, 0, unicode, -1, ansi, sizeof(ansi), NULL, NULL); return string(ansi); } int main(int argc, char *argv[]) { //한글 지역 설정 setlocale(LC_ALL, "korean"); //utf-8 한글 ansi 출력 string str = "서버"; string r; r = utf8_to_ansi(str); cout << str << endl; cout << r << endl; printf("%s\n", r.c_str()); //헥사값 char hex[] = "A003A0030101000E"; char *ptr; long value; value = strtoul(hex, &ptr, 16); cout << "value = " << value << endl; //변수 선언 SOCKET sock, clientsock; WSADATA wsa; struct sockaddr_in sockinfo, clientinfo; int clientsize; string msg; char message[BUFSIZE]; char buffer[BUFSIZE] = { 0 }; //변수 초기화 memset(message, 0x00, BUFSIZE); memset(buffer, 0x00, BUFSIZE); msg = "TCP/IP 소켓 프로그래밍"; strcpy(message, (char*)utf8_to_ansi(msg).c_str()); //소켓 버전 초기화 if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { str = "Winsock DLL 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } //TCP 소켓 생성 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) { str = "Soecket 생성 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } //소켓 주소 초기화 memset(&sockinfo, 0, sizeof(SOCKADDR_IN)); sockinfo.sin_family = AF_INET; //주소체계 AF_INET,AF_INET6,AF_LOCAL //포트 번호 / 주소 지정 int n_port = atoi(argv[1]); //문자열을 숫자로 변환 sockinfo.sin_port = htons(n_port); //숫자를 네트워크형태로 변환 sockinfo.sin_addr.s_addr = htonl(INADDR_ANY); //ip를 지정함 //소켓과 주소를 bind if (bind(sock, (SOCKADDR*)&sockinfo, sizeof(sockinfo)) == SOCKET_ERROR) { str = "bind 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } //소켓 listen if (listen(sock, 5) == SOCKET_ERROR) //[성공시 0,실패시 SOCKET_ERROR] { str = "listen 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } // str = "클라이언트로부터 접속을 기다리고 있습니다..."; printf("%s\n", (char*)utf8_to_ansi(str).c_str()); //struct sockaddr_in sockinfo 클라이언트 소켓 구조의 크기를 얻는다. clientsize = sizeof(clientinfo); //서버소켓과 클라이언트 구조와 크기로. 접속한 클라이언트 소켓 생성 clientsock = accept(sock, (SOCKADDR*)&clientinfo, &clientsize); if (clientsock == INVALID_SOCKET) //소켓핸들값이라서 INVALID_SOCKET로 확인 { str = "accept 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } //접속한 클라이언트 소켓으로. 메시지 배열의 크기 만큼 전송 printf("send : message"); send(clientsock, message, sizeof(message), 0); //접속한 클라이언트로 소켓으로. hex 배열의 크기 만큼 전송 send(clientsock, hex, sizeof(hex), 0); //사용한 소켓 종료 closesocket(sock); closesocket(clientsock); str = "성공"; printf("%s\n", (char*)utf8_to_ansi(str).c_str()); //윈도우 소켓 Cleanup WSACleanup(); return 0; } //오류 void ErrorHandling(char *message) { WSACleanup(); fputs(message, stderr); fputc('\n', stderr); _getch(); exit(1); }//클라이언트 순서:초기화-소켓생성-connect-소켓해제-원속 종료 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<winsock2.h> #include<conio.h> #include <iostream> #include <string> #include <conio.h> //Error: ‘Getch’ Was Not Declared In This Scope //https://www.dreamincode.net/forums/topic/341445-error-getch-was-not-declared-in-this-scope/ //htons function //https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-htons //WinSock32 //https://social.msdn.microsoft.com/Forums/vstudio/en-US/82ee2e1b-9957-4147-ac31-4e9ac82cbd59/winsock32?forum=vcgeneral #include <locale.h> // /workspace/test/src/client.c:76: error: ‘_getch’ was not declared in this scope #pragma comment(lib,"ws2_32.lib") #define BUFSIZE 2048 void ErrorHandling(char *message); using namespace std; //[WinAPi]WinAPI를 이용하여 cp949(ANSI) - utf8 인코딩 변환 C/C++ //http://blog.naver.com/PostView.nhn?blogId=nimi315&logNo=50093464158 //UTF-8 을 ANSI 로 변환 (한글 출력에 사용) string utf8_to_ansi(string &utf8) { WCHAR unicode[1500]; char ansi[1500]; memset(unicode, 0, sizeof(unicode)); memset(ansi, 0, sizeof(ansi)); ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, unicode, sizeof(unicode)); ::WideCharToMultiByte(CP_ACP, 0, unicode, -1, ansi, sizeof(ansi), NULL, NULL); return string(ansi); } // 소켓 함수 오류 출력 후 종료 //fn_WSAGetLastError("recv Error\n", recv_len, __FUNCTION__, __LINE__); void fn_WSAGetLastError(char* input_msg, int result, char* function_name, int line) { LPVOID lpMsgBuf; DWORD dwWSAErrorCode; // dwWSAErrorCode = WSAGetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwWSAErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); // MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg_input, MB_ICONERROR); printf("----------------------------------------\n"); printf("function name [%s()]\n", function_name); printf("line number [%d]\n", line); printf("input_msg [%s]\n", input_msg); printf("result [%d]\n", result); printf("wsa_error_code [%d]\n", dwWSAErrorCode); printf("wsa_error_string %s", (LPCTSTR)lpMsgBuf); printf("----------------------------------------\n"); LocalFree(lpMsgBuf); //오류시 무조건 종료' 되도록 되어 있지만. 상황에 맞게 수정해서 사용하세요. system("PAUSE\n"); exit(-1); //or exit(0); } // (char*) // /workspace/test/src/client.c:34: warning: deprecated conversion from string constant to ‘char*’ int main(int argc, char *argv[]) { //한글 지역 설정 setlocale(LC_ALL, "korean"); //utf-8 한글 ansi 출력 string str = "클라이언트"; string r; r = utf8_to_ansi(str); cout << str << endl; cout << r << endl; printf("%s\n", r.c_str()); //배열 문자 char hex[] = "A003A0030101000E"; char *ptr; long value; value = strtoul(hex, &ptr, 16); //변수 선언 SOCKET clientsock; WSADATA wsa; struct sockaddr_in sockinfo; char message[BUFSIZE]; int strlen; //인자값이 3개가 아니면. 종료 //client.exe argv[1] argv[2] if (argc != 3) { printf("Usage : %s <IP> <PORT> \n", argv[0]); exit(1); } //윈도우 소켓 초기화 if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { //성공하면 WSASTartup 함수는 0을 반환합니다. 그렇지 않으면 아래 나열된 오류 코드 중 하나를 반환합니다. //https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock/nf-winsock-wsastartup int r = WSAGetLastError(); printf("WSAGetLastError() : %d\n", r); fn_WSAGetLastError((char*)"WSAStartup() Error\n", 0, (char*)__FUNCTION__, __LINE__); str = "Winsock DLL 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } //TCP 소켓 생성 clientsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (clientsock == INVALID_SOCKET) { //https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock2/nf-winsock2-socket //If no error occurs, socket returns a descriptor referencing the new socket. //Otherwise, a value of INVALID_SOCKET is returned, //and a specific error code can be retrieved by calling WSAGetLastError. int r = WSAGetLastError(); printf("WSAGetLastError() : %d\n", r); fn_WSAGetLastError((char*)"socket() Error\n", clientsock, (char*)__FUNCTION__, __LINE__); str = "Soecket 생성 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } //struct sockaddr_in sockinfo 구조체 초기화 memset(&sockinfo, 0, sizeof(sockinfo)); //주소 패밀리 지정 sockinfo.sin_family = AF_INET; //포트 번호 지정 sockinfo.sin_port = htons(atoi(argv[2])); //IP 주소 지정 sockinfo.sin_addr.s_addr = inet_addr(argv[1]); //서버 소켓으로 접속 if (connect(clientsock, (SOCKADDR*)&sockinfo, sizeof(sockinfo)) == SOCKET_ERROR) { //https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock2/nf-winsock2-connect //If no error occurs, connect returns zero. //Otherwise, it returns SOCKET_ERROR, and a specific error code can be retrieved by calling WSAGetLastError. int r = WSAGetLastError(); printf("WSAGetLastError() : %d\n", r); fn_WSAGetLastError((char*)"connect() Error\n", SOCKET_ERROR, (char*)__FUNCTION__, __LINE__); str = "connect 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } //recv 받기 대기 //int recv( SOCKET s, __out_data_source(NETWORK) char *buf, int len, int flags ); //https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-recv //WSAGetLastError() //A set of flags that influences the behavior of this function. //See remarks below. See the Remarks section for details on the possible value for this parameter. //소켓 / 배열 데이터 / 배열 크기-1 strlen = recv(clientsock, message, sizeof(message)-1, 0); if (strlen == SOCKET_ERROR) { //윈도우 소켓은 리눅스 소켓과 조금 다릅니다. //반드시 MSDN 문서의 함수 설명을 확인하고. 사용하시기 바랍니다. //WSAGetLastError() 인것이 있고. //GetLastError() 인것이 있고. //int 가 리턴값인 경우가 있고. //DWORD 가 리턴값인 경우가 있습니다. //FormatMessage() 을 통해서. 오류값을 한글 설명으로 볼 수 있습니다. //오류가 발생하지 않으면 recv는 수신된 바이트 수를 반환하며, //buf 매개 변수로 가리키는 버퍼에 수신된 이 데이터가 포함됩니다. //연결을 정상적으로 종료한 경우 반환 값이 0입니다. //그렇지 않으면 SOCKET_ERROR 값이 반환되고 WSAGetLastError로 전화하여 특정 오류 코드를 검색할 수 있습니다. int r = WSAGetLastError(); printf("WSAGetLastError() : %d\n", r); //fn_WSAGetLastError("recv Error\n", recv_len, __FUNCTION__, __LINE__); fn_WSAGetLastError((char*)"recv Error\n", strlen, (char*)__FUNCTION__, __LINE__); //int WSAGetLastError(); //https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock/nf-winsock-wsagetlasterror str = "recv 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } //소켓 / 배열 데이터 / 배열 크기-1 strlen = recv(clientsock, hex, sizeof(hex)-1, 0); if(strlen == SOCKET_ERROR) { int r = WSAGetLastError(); printf("WSAGetLastError() : %d\n", r); //fn_WSAGetLastError("recv Error\n", recv_len, __FUNCTION__, __LINE__); fn_WSAGetLastError((char*)"recv Error\n", strlen, (char*)__FUNCTION__, __LINE__); //int WSAGetLastError(); //https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock/nf-winsock-wsagetlasterror str = "recv 실패"; ErrorHandling((char*)utf8_to_ansi(str).c_str()); } // string str1 = "받은 데이터는 16진수로"; string str2 = "입니다."; printf("%s 0x%08X %s\n", (char*)utf8_to_ansi(str1).c_str(), htons(strlen), (char*)utf8_to_ansi(str2).c_str()); str1 = "받은 데이터는 십진수로"; str2 = "입니다."; printf("%s %d %s\n", (char*)utf8_to_ansi(str1).c_str(), strlen, (char*)utf8_to_ansi(str2).c_str()); // printf(" Server say message: %s \n", message); printf(" Server say hex : %s \n", hex); //소켓 종료 closesocket(clientsock); //소켓 Cleanup WSACleanup(); return 0; } //오류 void ErrorHandling(char *message) { WSACleanup(); fputs(message, stderr); fputc('\n', stderr); _getch(); exit(1); }----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
댓글 달기