반응형
SMALL
[Client.c]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | /* */ #define _WINSOCK_DEPRECATED_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include <winsock2.h> #pragma comment(lib, "ws2_32"); //pragma comment(lib, "wsock32.lib"); #define BUFSIZE 512 void err_quit(const char* msg) { LPVOID IpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&IpMsgBuf, 0, NULL); exit(-1); } int main(int argc, char* argv[]) { //원속(윈도우 소켓) 초기화 --> 윈속 함수 호출을 위한 라이브러리의 메모리 LOAD를 의미 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) //WSAStartup함수 -> 프로그램에서 요구하는 윈도우 소켓 버전 // int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData); // --> wVersionRequested(프로그래머가 사용할 윈속의 버전정보 전달), // --> lpWSAData(WSEATA라는 구조체 변수의 주소 값 전달) return -1; /* 윈속 버전을 사용할 수 있는지 윈도우에 확인하는 함수 if (WSAStartup(WINSOCK_VERSION, &wsaData) != 0) { printf("WSAStartup 실패, 에러 코드 = %d\n", WSAGetLastError()); return; } */ //socket() /* int socket(int domain, int type, int protocol); --> 성공 시 파일 디스크립터, 실패시 -1 반환 -- domain : 소켓이 사용할 프로토콜 체계(Protocol Family) 정보 전달. -- type : 소켓의 데이터 전송방식에 대한 정보 전달. -- protocol 두 컴퓨터간 통신에 사용되는 프로토콜 정보 전달 --> 모두 프로토콜 정보와 관련 소켓의 타입 - 전송방식, 생성될 때 타입도 결정 */ SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); //TCP/IP용 소켓 생성 // SOCKET socket( int af, int type, int protocol); // 성공 시 소켓 핸들, 실패 시 INVALID_SOCKET반환 // SOCK_STREAM -> 연결지향형 (중간에 데이터 소멸 없음, 전송 순서대로 수신, 데이터 경계 없음, 1대1구조) if (sock == INVALID_SOCKET) err_quit("socket()"); printf("소켓이 생성되었습니다.\n"); //MessageBox(NULL, "TCP 소켓성공", "알림", MB_OK); /* * sockaddr_in * { * sin_family 주소체계정보 저장 * sin_port 16비트 port 번호 저장, 네트워크 바이트 순서로 저장 * sin_addr 32비트 ip주소정보 저장, 네트워크 바이트 순서로 저장, 멤버 sin_addr의 구조체 자료형 in_addr사실상 32비트 정수 자료형 * }192.168.0.57 */ //connect() // int connect(SOCKET s, const struct sockaddr * name, int namelen); // --> 성공시 0, 실패시 SOCKET_ERROR 반환 SOCKADDR_IN serveraddr; ZeroMemory(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; // IPv4(4바이트) 인터넷 프로토콜에 적용하는 주소체계 serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 지정된 주소를 대신하여 사용할 수 있는 로컬 호스트 번지(사용하는 컴퓨터에 직접 네트워크로 연결) /* * in_addr_t inet_addr(const char * string); * --> 성공 시 빅 엔디안으로 변환된 32비트 정수 값, 실패시 INADDR_NONE 반환 * --> "211.214.107.99"와 같이 점이 찍힌 10진수로 표현된 문자열을 전달하면, 해당 문자열 정보를 참조해서 IP주소 정보를 32비트 정수형으로 반환 */ serveraddr.sin_port = htons(9000); connect(sock, (SOCKADDR*)&serveraddr, sizeof(serveraddr)); printf("connect 연결요청!!\n"); //서버로 보낼 스트링 설정 char buf[BUFSIZE + 1]; sprintf(buf, "hello world!"); //send() // int send(SOCKET s, const char * buf, int len, int flags); // --> 성공 시 전송된 바이트 수, 실패시 SOCKET_ERROR 반환 // -- s : 데이터 전송 대상과의 연결을 의미하는 소켓의 핸들 값 전달. // -- buf : 전송할 데이터를 저장하고 있는 버퍼의 주소 값 전달. // -- len : 전송할 바이트 수 전달 // -- flags : 데이터 전송 시 적용할 다양한 옵션 정보 전달 // -- send(sock, buf, strlen(buf), 0); printf("메세지를 보냅니다.\n"); //closesocket() // int closesocket(SOCKET s0; // --> 성공시 0, 실패 시 SOCKET_ERROR 반환 closesocket(sock); // 윈속 종료 // 다음 함수가 호출되면 윈속 관련 함수의 호출이 불가능해지므로, // 프로그램이 종료되기 직전에 호출하는 것이 일반적 WSACleanup(); // 반환값 / 성공시 0, 실패시 SOCKET_ERROR반환 -- 윈도우 운영체제에 반환이 되면서 윈속 관련 함수의 호출이 불가능해짐. -> 프로그램 종료 직전에 호출 return 0; } | cs |
[Server.c]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #define _WINSOCK_DEPRECATED_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #include <winsock2.h> #include<stdio.h> #include<stdlib.h> #pragma comment(lib, "ws2_32"); #define BUFSIZE 512 void err_quit(const char* msg) { LPVOID IpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&IpMsgBuf, 0, NULL); exit(-1); } int main(int argc, char* argv[]) { int retval; //원속초기화 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) return -1; //socket() SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0); if (listen_sock == INVALID_SOCKET) err_quit("socket()"); printf("소켓이 생성되었습니다\n"); //MessageBox(NULL, "TCP 소켓성공", "알림", MB_OK); //bind() /* * sockaddr_in * { * sin_family 주소체계정보 저장 * sin_port 16비트 port 번호 저장, 네트워크 바이트 순서로 저장 * sin_addr 32비트 ip주소정보 저장, 네트워크 바이트 순서로 저장, 멤버 sin_addr의 구조체 자료형 in_addr사실상 32비트 정수 자료형 * } */ SOCKADDR_IN serveraddr; ZeroMemory(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); // // addr.sin_addr.s_addr=htonl(INADDR_ANY); -> 현재 실행중인 IP를 소켓에 부여할때 사용, 서버 프로그램의 구현에 주로 사용 serveraddr.sin_port = htons(9000); // // int bind(SOCKET s, const struct sockaddr * name, int namelen); // --> 성공 시 소켓 핸들, 실패시 INVALID_SOCKET 반환 // int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen); // -- sockfd: 주소정보를 할당할 소켓의 파일 디스크립터 // -- myaddr: 할당하고자 하는 주소정보를 지니는 구조체 변수의 주소 값 // -- addrlen: 두 번째 인자로 전달된 구조체 변수의 길이 정보 bind(listen_sock, (SOCKADDR*)&serveraddr, sizeof(serveraddr)); printf("Bind 완료 되었습니다.\n"); //listen() // int listen(SOCKET s, int backlog); // --> 성공시 0, 실패시 SOCKET_ERROR반환 listen(listen_sock, SOMAXCONN); printf("connect 연결을 기다리는 중..\n"); //통신에 사용할 변수 SOCKET client_sock; SOCKADDR_IN clientaddr; int addrlen; char buf[BUFSIZE + 1]; //accept() addrlen = sizeof(clientaddr); // SOCKET accept(XOCKET s, struct sockaddr * addr, int * addrlen); // --> 성공 시 소켓 핸들, 실패 시 INVALID_SOCKET 반환 client_sock = accept(listen_sock, (SOCKADDR*)&clientaddr, &addrlen); printf("요청을 받았습니다.\n"); //recv() // int recv(SOCKET s, const char * buf, int len, int flags); // --> 성공 시 전송된 바이트 수(단 EOF 전송시 0), 실패시 SOCKET_ERROR 반환 // -- s : 데이터 전송 대상과의 연결을 의미하는 소켓의 핸들 값 전달. // -- buf : 전송할 데이터를 저장하고 있는 버퍼의 주소 값 전달. // -- len : 전송할 바이트 수 전달 // -- flags : 데이터 전송 시 적용할 다양한 옵션 정보 전달 retval = recv(client_sock, buf, BUFSIZE, 0); printf("메세지를 수신하였습니다.\n"); //받는 데이터 출력 buf[retval] = '\0'; printf("[TCP/%s:%d] %s\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buf); //closesocket closesocket(listen_sock); //원속 종료 WSACleanup(); return 0; } | cs |
[문제]
1. 서버가 계속 살아있게 만들어야 한다.
--while문 사용
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #define _WINSOCK_DEPRECATED_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #include <winsock2.h> #include<stdio.h> #include<stdlib.h> #pragma comment(lib, "ws2_32"); #define BUFSIZE 512 void err_quit(const char* msg) { LPVOID IpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&IpMsgBuf, 0, NULL); exit(-1); } int main(int argc, char* argv[]) { int retval; //원속초기화 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) return -1; //socket() SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0); if (listen_sock == INVALID_SOCKET) { err_quit("socket()"); } printf("소켓이 생성되었습니다\n"); //bind() SOCKADDR_IN serveraddr; ZeroMemory(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(5001); if (bind(listen_sock, (SOCKADDR*)&serveraddr, sizeof(serveraddr))) { err_quit("socket()"); } printf("Bind 완료 되었습니다.\n"); //listen() if (listen(listen_sock, SOMAXCONN) != 0) { err_quit("socket()"); closesocket(listen_sock); WSACleanup(); return 0; } printf("connect 연결을 기다리는 중..\n"); //통신에 사용할 변수 SOCKET client_sock; SOCKADDR_IN clientaddr; int addrlen; char buf[BUFSIZE + 1]; //accept() addrlen = sizeof(clientaddr); client_sock = accept(listen_sock, (SOCKADDR*)&clientaddr, &addrlen); if (client_sock == INVALID_SOCKET) { err_quit("socket()"); closesocket(listen_sock); WSACleanup(); return 0; } printf("요청을 받았습니다.\n"); //recv() while (1) { retval = recv(client_sock, buf, BUFSIZE, 0); printf("메세지를 수신하였습니다.\n"); //받는 데이터 출력 buf[retval] = '\0'; printf("[TCP/%s:%d] %s\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buf); } //closesocket closesocket(listen_sock); //원속 종료 WSACleanup(); return 0; } | cs |
반응형
LIST
'혼자 코딩(C언어)' 카테고리의 다른 글
난... 아무것도 모르는 감자... (0) | 2022.09.02 |
---|---|
c언어 윈도우 기반 TCP/IP 서버 다중 접속 예제 - 002 (0) | 2022.08.08 |
C언어 계산기 프로그램을 마치며 (0) | 2022.08.02 |
C언어 계산기 프로그램 5안(우선순위 괄호 계산기) (0) | 2022.07.26 |
C언어 계산기 프로그램 4안(연산자 중복시 멈춤) (0) | 2022.07.21 |
댓글