네트워크 프로그래밍
소켓이라는 것을 기반으로 프로그래밍을 하기 때문에 소켓 프로그래밍이라고도 함.
네트워크로 연결된 둘 이상의 컴퓨터 사이에서의 데이터 송수신 프로그램의 작성을 의미함.
소켓에 대한 간단한 이해
네트워크의 연결 도구
운영체제에 의해 제공이 되는 소프트웨어적인 장치
소켓의 비유와 분류
TCP 소켓은 전화기에 비유될 수 있음
소켓은 socket 함수의 호출을 통해서 생성됨
단 전화를 거는 용도의 소켓과 전화를 수신하는 용도의 소켓 생성 방법에는 차이가 있다.
1 2 3 4 | #include<sys/socket.h> int socket(int domain, int type, int protocol); | cs |
소켓의 생성
=> 성공시 파일 디스크립터, 실패 시 -1 반환
소켓의 주소 할당 및 연결
전화기에 전화번호가 부여되듯이 소켓에도 주소정보가 할당
소켓의 주소정보는 IP와 PORT번호로 구성됨
1 2 3 | #include<sys/socket.h> int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen); | cs |
주소의 할당
=> 성공시 0, 실패 시 -1 반환
연결요청이 가능한 상태의 소켓
연결요청이 가능한 상태의 소켓은 걸려온느 전화를 받을 수 있는 상태에 비유할 수 있다.
전화를 거는 용도의 소켓은 연결요청이 가능한 상태의 소켓이 될 필요가 없다. 이는 걸려오는 전화를 받는 용도의 소켓에서 필요한 상태이다.
1 2 3 | #include<sys/socket.h> int listen(int sockfd, int backlog); | cs |
연결요청 가능한 상태로 변경
=> 성공시 0, 실패시 -1 반환
소켓에 할당된 IP와 Port번호로 연결요청이 가능한 상태가 됨
연결요청의 수락
걸려오는 전화에 대해서 수락의 의미로 수화기를 드는 것에 비유 할수 있다.
연결요청이 수락되어야 데이터의 송수신이 가능
수락된 이후에 데이터 송수신이 양방향성으로 됨
1 2 3 | #include<sys/socket.h> int accept(int sockfd, int backlog); | cs |
연결을 요청하는 소켓의 구현
리스닝 소켓과 달리 구현의 과정이 매우 간단
'소켓의 생성'과 연결의 요청'으로 구분
소켓을 사용하기 위한 연결
Server | Client |
소켓 생성(socket) IP/PORT (bind) 요청대기(listen) 수락(accept) Read/Write 종료(close) | 소켓 생성(Socket) 연결 요청(Connect) Read/Write 종료(close) |
소켓의 종류
TCP | UDP |
동기식 연결 방식 데이터가 손실되지 않음 데이터가 순서대로 전달됨 | 비동기식 연결방식 데이터 손실 발생할 수 있음 속도가 빠름(상대적) |
간단한 예제 (C언어)
서버 : 포트를 열고 대기한 상태에서 클라이언트가 접속하면 Hello World를 전송
클라이언트 : 서버의 IP와 PORT번호를 입력하여 서버에 접근하자마자 Read하고 받은 데이터를 출력
서버와 클라이언트 프로젝트를 각각 만들어야함
프로젝트에 라이브러리 추가
프로젝트 오른쪽 클릭 -> 속성
링커 -> 입력으로 이동
추가 종속성 -> 편집 누르기
ws2_32.lib 를 적기
Hello_Client_win.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 | #include <stdio.h> #include <stdlib.h> #include <winsock2.h> void ErrorHandling(char* message); int main(int argc, char* argv[]) { WSADATA wsaData; SOCKET hSocket; SOCKADDR_IN servAddr; char message[30]; int strLen; if(argc!=3) { printf("Usage : %s <IP> <port>\n", argv[0]); exit(1); } if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) ErrorHandling("WSAStartup() error!"); hSocket=socket(PF_INET, SOCK_STREAM, 0); if(hSocket==INVALID_SOCKET) ErrorHandling("hSocketet() error"); memset(&servAddr, 0, sizeof(servAddr)); servAddr.sin_family=AF_INET; servAddr.sin_addr.s_addr=inet_addr(argv[1]); servAddr.sin_port=htons(atoi(argv[2])); if(connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr))==SOCKET_ERROR) ErrorHandling("connect() error!"); strLen=recv(hSocket, message, sizeof(message)-1, 0); if(strLen==-1) ErrorHandling("read() error!"); printf("Message from server: %s \n", message); closesocket(hSocket); WSACleanup(); return 0; } void ErrorHandling(char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } | cs |
Hello_server_win.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 | #include <stdio.h> #include <stdlib.h> #include <winsock2.h> void ErrorHandling(char* message); int main(int argc, char* argv[]) { WSADATA wsaData; SOCKET hServSock, hClntSock; SOCKADDR_IN servAddr, clntAddr; int szClntAddr; char message[]="Hello World!"; if(argc!=2) { printf("Usage : %s <port>\n", argv[0]); exit(1); } if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0) ErrorHandling("WSAStartup() error!"); hServSock=socket(PF_INET, SOCK_STREAM, 0); if(hServSock==INVALID_SOCKET) ErrorHandling("socket() error"); memset(&servAddr, 0, sizeof(servAddr)); servAddr.sin_family=AF_INET; servAddr.sin_addr.s_addr=htonl(INADDR_ANY); servAddr.sin_port=htons(atoi(argv[1])); if(bind(hServSock, (SOCKADDR*) &servAddr, sizeof(servAddr))==SOCKET_ERROR) ErrorHandling("bind() error"); if(listen(hServSock, 5)==SOCKET_ERROR) ErrorHandling("listen() error"); szClntAddr=sizeof(clntAddr); hClntSock=accept(hServSock, (SOCKADDR*)&clntAddr,&szClntAddr); if(hClntSock==INVALID_SOCKET) ErrorHandling("accept() error"); send(hClntSock, message, sizeof(message), 0); closesocket(hClntSock); closesocket(hServSock); WSACleanup(); return 0; } void ErrorHandling(char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } | cs |
서버,클라이언트 둘다 실행시 main 에 매개변수를 줘야 실행이 됨
Cmd를 이용한 main문에 매개변수 전달 (프로젝트 빌드 후)
서버
실행 파일 + 포트번호 매개변수 입력
클라이언트 (출력결과)
IP번호 (현재는 같은 컴퓨터에서 실행해서 로컬호스트인 127.0.0.1 입력)와 서버에서 연 PORT번호 입력
[출처] (C) 소켓 프로그램|작성자 길가다주은노트북
'프로그래밍 > C' 카테고리의 다른 글
(C언어) 파일입출력 (0) | 2016.07.09 |
---|---|
(C언어) 이진 트리의 순회 프로그램 (0) | 2016.07.09 |
(C언어) 순차 자료구조를 이용한 최대 히프 프로그램 (0) | 2016.07.09 |
(C언어) 이진 탐색 트리의 연산 프로그램 (0) | 2016.07.09 |
(C언어) 큐를 이용한 서비스 요청 고객 관리 프로그램 (0) | 2016.07.09 |