에러가 났을 때 왜 에러가났는지?(디버깅이 중요)
다음주에 오기전까지 프로그램을 돌려보고 오도록!
레이어 2에 직접 접속해서 프로그램을 할 수 있다.
소켓은 대부분 2,4에 집중되어 있다. 만약 분산시스템을 적용하면 운용 쪽에서 추가적으로 해서 할 수 있다. 전산쪽에서 많이 하는 게 저런 것들...
이름은 많다. socket : BSD unix에서 먼저 만들어서 배포한 이름. 윈도우, 맥 등에서도 Windock, MacTCP등을 만들었다. TLI, ATNT등이 있는데 다들 소켓에게 영향을 받았다.
소켓 쪽에서 할 때 크게 세가지 타입이 있다.
stream - oriented : TCP 여기서 stream은 TCP가 byte stream이라는 뜻
datagram : UDP
raw IP
socket interface
socket을 만들면 descriptor가 생긴다. 자연상태에서는 항상 3번이다. 리눅스에서는 모든 인터페이스가 파일이다. 파일쪽에서 이미 0,1,2번을 사용하고 있다. 그래서 처음 열면 3번, 4번,5번 이렇게 진행된다.
왜 해야 돼>../?
프로그램을 하려면 인터넷에서는 어떤 프로토콜을 사용할 것인지?(TCP, UDP..) 그리고 자신의 address, port가 뭔지 define해야 한다. 데이터를 보낼때 상대방의 address, port가 필요하다. 이것들을 소켓과 연관시키는 과정이 API로 어떻게 저렇게 하면 된다. 소켓을 통해 어떤 프로토콜을 만들 것인가?socket() 에 대해. 특히 서버쪽에서는 자신의 소켓에다가 연관을 시키기 위해 어떤 IP와 portnumber? bind(), 클라이언트에서도 자신의 address와 port가 필요하지만 푸르진 않는다. 어떤 프로토콜에서는 클라이언트가 특정 넘버를 가지고 동작하는 경우가 있다. 밑에 정보가 없어서. 그런 경우는 클라리언트도 바인드를 하지만 일반적으로는 안 해도 된다. 왜냐하면 OS가 알아서 해주기 때문. client는 불러도 안 불러도 상관없다..
상대방의 IP, port넘버를 소켓과 연관시키기 위해 TCP에서는 커넥션을 맺어야 하기에 connect()로부른다. 이때 argument에 dest IP, portnumber을 주고 connection establishent를 한다. UDP에서는 connection을 하지 않기에 데이터를 보낼때마다 데이터랑 상대방 IP, port를 같이 보낸다. datat를 보낼때 data + destIp&port로 보낸다는 것.
header를 놓치면 에러가 난다. 소켓을 만들면서 어떤 프로토콜을 사용할 것인지 인자로 넣어준다.
family는 어떤 프로토콜을 사용할 것인지? PF는 프로토콜 패밀리인데 inet은 인터넷 v4를 사용한다는 것. inet6는 v6인 것. 소켓이 다른 쪽에 있는 호스트와 커뮤니케이션 할 때 뿐 아니라 프로테스 to 프로세스를 용도로 할 수도 있지만 다른 메커니즘이 있다. 하지만 못 쓰는 건 아니다. 그 다음 어떤 서비스 타입을 사용할 것인가.
어떤 socket에 stream서비스 중에서 어떤 프로토콜을 하겠다 이렇게 생각했지만 지금은 stream서비스를 하는게 TCP하나이기 때문에 int type 이후 int protocol 이 의미가 없어지기에 '0'을 넣어준다.
프로토콜은 일반적으로 0을 넣어준다.
그다음 바인드는 만들어진 소켓에다가 자신의 IP, port를 묶어주는 것. 자신이 만든 소켓 디스크립터에 그 정보가 *addr에 들어가 있다. 에러는 -1이다.
두개의 구조체는 사이즈는 똑같다. 반드시 나머지 부분은 0으로 채워야. 소켓을 TCP를 만들고 0으로 메모리 셋을 하고 요즘은 bzero안하고 memset을 쓴다. 0으로 만들어주고 패밀리에게 인터넷v4를 사용하겠다고 하고 포트넘버를 주고 포맷을 바꾸고 자신의 주소를 준다. 일반적으로 bind로 부르는 걸 서버에서 한다. 서버에서는 주로 NADDR_ANY를 준다 대부분 0이다. inaddr_any를 주면 컴퓨터 network interface카드가 와이어리스, 이더넷 이렇게 2개가 있다. 큰 대용량 서버에서는 interface card가 여러개를 가지고 있다. 그런데 IP주소는 card마다 주어진다. 한 컴퓨터가 IP를 여러개를 가지게 된다. 그러면 서버프로그램이 돌고 있는데 클라이언트가 어떤 IP주로르 통해 들어올지 모른다. 그럴 때 INADDR_ANY로 주면 자신이 어디로 들어오든지 다 받게 된다. 그러니까 무조건 이렇게 해야 함. 그 다음에 바인드를 해서 줘야 한다. 처음에는 error체크를 하기가 귀찮..그래서 처음에는 할 필요가 없는데 밑에 bind에는 반드시 해야 한다.
그리고 htons, htonl은 오더링이 틀리다. 그래서 byte odering을 위해서 little과 big이 값이 완전히 뒤집어져서 간다. little endian은 주소가 낮은 쪽에 ls가 간다. big endian은 주소가 높은 족에 . 지금은 대부분의 intel이니까 옛날에는 뭐 이런 저런 거 많았다.
connect()
일반적으로 커넥트는 TCP의 CLient가 쓰는데 UDP에서도 가끔 쓰는데 그렇다고 oriendted는 아님. 그냥 데이터를 보낼때마다 IP, port를 주기 귀찮으면 상대방에 대한 IP port를 정보를 주는게 COnnect니까 그렇게 해놓아면 sendto()할때마다 줄 필요없어서 하기도 하는데 될 수 있으면 안 하는 게 좋음. 그래서TCP쪽에서 클라이언트에서 그래서 소켓을 하고 포트넘버를 자기 정보를 주고..얘를 직접 dotted docimal 32비트니까 8888비트씩 나눠서 각각 decimal로 0~255까지 구분을 . . . . 이런 정보를 주면 32bti주소를 준다. 그리고 내부에서 알아서 host ordering big endian처럼 바꿔준다. 그리고나서 connect를 주면..그 다음에 서버에서는 listen()을 한다. os한테 syn packet을 받고 다시 ack을 보내는 과정이 일어난다. TCP만 .
backlog는 자기가 buffer되어 있어서 최대로받을 수 있는 수를 말하는데 실제로 잘 안 된다. 3으로 줘도 connection3개는 되고 4개는 reejct이ㅗ디어야 하는데 시스템에서 무시하고 그냥 하는 것 같음. 주로 5를 주는게 일반적. 그런데 의미는 딱히
accept()도 서버에서. 여기서 이미 listen쪽에서 3핸드쉐이킹이 끝난 것. accept은 이미 그게 끝난 걸 받아주는 것. addr은 포트 넘버가 정보를 싣어서 리턴 되는 벨류가 있죠? 얘도 socket discripor가 ..여기서 하는 커넥션 리퀘스트로 받는 것. 여기는 3핸드쉐이킹 끝나고 나서 클라이언트랑 같이 하는 것. 얘 가지고 하는 것. 많은 학생이 sd로 통신을 하려고 하는데 그게 아니고 addr로 해야 함. 얘는 커넥션을 받아들이는 쪽이다.