Server
- 1_server
: 기본 서버 구조1234567891011121314151617181920212223242526272829303132333435363738#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int
main()
{
// 1. socket 생성
int
sock = socket(PF_INET, SOCK_STREAM, 0);
// 2. bind() : 소켓 주소 지정
struct
sockaddr_in saddr = {0, };
saddr.sin_family = AF_INET;
saddr.sin_port = htons(4000);
// 연결을 받을 주소
saddr.sin_addr.s_addr = inet_addr(
"127.0.0.1"
);
bind(sock, (
struct
sockaddr*)&saddr,
sizeof
saddr);
// 3. 연결 대기 상태로 만든다. : listen
listen(sock, 5);
// 4. 클라이언트 요청 수락 : accept
struct
sockaddr_in caddr = {0, };
socklen_t clen =
sizeof
(caddr);
int
csock = accept(sock, (
struct
sockaddr*)&caddr, &clen);
printf
(
"연결이 수립되었습니다.\n"
);
close(csock);
close(sock);
}
- 2_server
: 여러 클라이언트 받아들이기
123456789101112131415161718192021222324252627282930313233343536373839#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int
main()
{
int
sock = socket(PF_INET, SOCK_STREAM, 0);
struct
sockaddr_in saddr = {0, };
saddr.sin_family = AF_INET;
saddr.sin_port = htons(4000);
// saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 문제점 : 127.0.0.1로 오는 연결만 받을 수 있다.
// 해결방법 : INADDR_ANY(0.0.0.0);
saddr.sin_addr.s_addr = INADDR_ANY;
// 0.0.0.0
bind(sock, (
struct
sockaddr*)&saddr,
sizeof
saddr);
listen(sock, 5);
while
(1)
{
struct
sockaddr_in caddr = {0, };
socklen_t clen =
sizeof
(caddr);
int
csock = accept(sock, (
struct
sockaddr*)&caddr, &clen);
char
* cip = inet_ntoa(caddr.sin_addr);
printf
(
"Connected from %s\n"
, cip);
close(csock);
}
close(sock);
}
Client
- 1_client ~ 2_client
: 기본 클라이언트 구조
12345678910111213141516171819202122232425262728293031#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
int
main()
{
int
sd = socket(PF_INET,
SOCK_STREAM,
IPPROTO_TCP);
struct
sockaddr_in addr = {0, };
addr.sin_family = AF_INET;
addr.sin_port = htons(4000);
addr.sin_addr.s_addr = inet_addr(
"127.0.0.1"
);
int
ret = connect(sd, (
struct
sockaddr*)&addr,
sizeof
(addr));
if
(ret == -1) {
perror
(
"connect()"
);
return
-1;
}
printf
(
"Connection succeed!!\n"
);
close(sd);
}
- 3_client
: TIME_WAIT 문제 확인
123456789101112131415161718192021222324252627282930313233#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
int
main()
{
int
sd = socket(PF_INET,
SOCK_STREAM,
IPPROTO_TCP);
struct
sockaddr_in addr = {0, };
addr.sin_family = AF_INET;
addr.sin_port = htons(4000);
addr.sin_addr.s_addr = inet_addr(
"127.0.0.1"
);
int
ret = connect(sd, (
struct
sockaddr*)&addr,
sizeof
(addr));
if
(ret == -1) {
perror
(
"connect()"
);
return
-1;
}
printf
(
"Connection succeed!!\n"
);
sleep(5);
close(sd);
}
- 3_server
: bind(): Address already in use 해결
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 | #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> // 1. bind() : Adress already in use // 먼저 연결을 종료한 측의 소켓은 유지되어야 한다. - TIME_WAIT // => TIME_WAIT 상태가 종료 되기 이전에 해당 포트로 서버를 바인드 // 하는 것이 불가능하다. // 2. TIME_WAIT : 같은 포트의 연결을 손상 시킬 수 있다. // 3. 클라이언트 포트는 동일한 포트로 바인딩 되지 않는다. // 4. 최신 네트워크 커널의 구현은 SYN의 시퀀스 번호가 TIME-WAIT 상태의 // 연결로부터 마지막 시퀀스 번호보다 클 경우에만 연결을 허용한다. // 5. TIME_WAIT은 먼저 연결을 종료한 쪽에서 발생한다. // 클라이언트는 포트가 변경되기 때문에 문제가 없다. int main() { int sock = socket(PF_INET, SOCK_STREAM, 0); struct sockaddr_in saddr = {0, }; saddr.sin_family = AF_INET; saddr.sin_port = htons(4000); saddr.sin_addr.s_addr = INADDR_ANY; // 0.0.0.0 //---------------- // 6. 해결방법 // 서버는 약속된 포트로부터 연결을 받아야 하므로 // 반드시 주소를 재할당 할 수 있도록 변경해주어야 한다. int option = true ; socklen_t optlen = sizeof (option); setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option, optlen); //----------------- int ret = bind(sock, ( struct sockaddr*)&saddr, sizeof saddr); if (ret == -1) { perror ( "bind()" ); return -1; } listen(sock, 5); struct sockaddr_in caddr = {0, }; socklen_t clen = sizeof (caddr); int csock = accept(sock, ( struct sockaddr*)&caddr, &clen); close(csock); close(sock); } |
'Programing > Server Model' 카테고리의 다른 글
서버 모델 - I/O 모델 개요 (0) | 2016.02.22 |
---|---|
서버 모델 - 리눅스 소켓 프로그래밍(3) (0) | 2016.02.22 |
서버 모델 - 리눅스 소켓 프로그래밍(2) (0) | 2016.02.18 |
서버 모델 - 소켓 프로그래밍 (0) | 2016.02.18 |
서버 모델 - 기초 (0) | 2016.02.16 |