클라이언트 서버 통신이 이루어지기 위해서는 서버 프로세스가 실행되고 있어야 한다. 프로세스가 실행되기 위해서는 서버 소켓을 만든다. 서버는 소켓을 통해 데이터를 주고받는다. 클라이언트 측에서도 역시 클라이언트 소켓을 만들어야 ip주소와 포트번호를 세그먼트에 붙여 내보낼 수 있다. 이를 다시 서버소켓을 통해 읽어들일 수 있다. 또 역시 서버 소켓을 통해 응답을 써서 클라이언트 쪽으로 줄 수 있다. 이때 어느 클라이언트에게 가는지 ip주소와 포트번호를 명시해야 한다. 그런데 클라이언트 ip주소와 포트번호는 클라이언트 프로세스도 모른다. 이는 클라이언트 프로세스가 소켓을 만들때 운영체제가 명시적이 아닌 암시적으로 매핑을 하기 때문이다. 그래서 서버는 클라이언트로부터 온 데이터에 이 번호가 붙어 있기 때문에 이를 추출해 포트번호를 알아낸다. 따라서 서버가 이 정보를 통해 클라이언트에 정보를 보내면 클라이언트 소켓을 통해 데이터를 읽어들이고 클라이언트 소켓은 닫힌다.
위는 파이썬에서 udp 클라이언트 소켓 프로그래밍의 예시다. 소켓 라이브러리를 상속하고 서버의 호스트 네임과 서버 소켓의 포트번호를 지정한다. 이후 클라이언트 소켓을 생성하고 인자로 데이터 딜리버리에 사용할 네트워크와 udp transport를 사용할 것임을 명시한다. 이를 명시하는 이유는 운영체제가 소켓에 클라이언트 주소와 포트번호를 매핑하기 때문에 포트번호의 주소가 어느 패밀리의 주소이고 어떤 트랜스포트를 사용하는지 알려줘야 하기 때문이다. 이후 키보드로부터 사용자의 인풋을 받고, 클라이언트 소켓에 메세지를 써주고 서버네임과 서버포트를 인자로 넣어준다. 또 서버가 수정된 센텐스를 보내면 클라이언트 소켓을 통해 받는다. 그러면 그 메세지를 출력하고 소켓을 닫는다.
위는 파이썬에서 udp 서버 소켓 프로그래밍의 예시다. 서버 포트를 지정하고 서버소켓을 만든다. 그 다음 서버소켓과 서버 포트번호를 바인딩 시킨다. 이렇게 서버의 포트번호가 명시적으로 드러나는 것이 클라이언트 소켓과의 차이다. 서버가 받을 준비가 됐다는 메세지가 뜨면 루프를 영구적으로 돈다. 서버 소켓에 메세지의 데이터와 데이터를 보낸 이의 주소가 도착하면 message에 데이터를 뽑고, clientaddress라는 변수에 주소를 뽑는다. 메세지를 대문자로 바꾼 후 modifiedmessage 변수에 집어넣고 서버 소켓을 통해 클라이언트에 내보내는데, 첫 인자로 내보낼 데이터, 두 번째 인자로 클라이언트의 주소를 넣는다. 이는 데이터로부터 받은 메세지에서 추출한 것이다. 이 주소는 클라이언트 프로세스가 모른다. 운영체제가 암묵적으로 할당한 것이기 때문이다. 이는 서버 측에서 주소를 추출해서 데이터를 내보낼때 명시해 준다.
다음은 tcp 소켓 프로그래밍이다. 이 역시 서버가 실행 중이여야 하고 서버는 소켓을 생성하는데 이 용도는 클라이언트의 컨택트를 받아들이기만 하는 것이다. 소켓을 만들면 클라이언트는 tcp 소켓을 통해 데이터를 내보내려 할 텐데 핸드셰이킹이 먼저 필요하다. 이를 위해 본인이 접촉할 서버의 ip주소와 포트번호를 명시해준다. 그러면 클라이언트 소켓을 생성하여 클라이언트 tcp가 서버 tcp와 커넥션을 맺는다. 서버 쪽 tcp에서는 클라이언트의 접촉을 받아들이고 해당 클라이언트만을 위한 소켓을 새로 생성한다. 따라서 tcp로 데이터를 주고받을 때는 커넥션을 셋업 하고 나면 목적지를 명시하지 않는다. 목적지를 명시하지 않아도 새롭게 생성된 소켓을 통해 내려온 데이터는 오직 하나의 클라이언트로만 전달되는 것을 tcp가 인지하고 있기 때문이다. 또 새로운 클라이언트마다 소켓을 만드므로 tcp는 각 커넥션마다 소켓을 별도로 열고 있다. 그래서 한 소켓을 통해 주고받는 동안 다른 소켓으로 주고받을 수 있다. 이렇게 하는 이유는 tcp는 byte-stream을 주고받기 때문이다. udp는 각 메세지가 독립적이므로 메세지를 하나 받고 답을 보내주면 끝이다. 그러나 tcp는 한 클라이언트와 커넥션을 맺으면 임의적인 길이의 바이트스트림을 주고받기 때문에 그것을 주고 받는 동안 다른 클라이언트와 교환을 못하면 안 된다.
다음은 tcp를 통한 클라이언트-서버 소켓 인터렉션이다. 먼저 서버가 서버 소켓을 만들면 서버소켓의 포트번호를 명시적으로 지정하고 bind시킨다. 이후 커넥션 요청이 들어오면 서버 소켓을 새롭게 생성하고 이를 커넥션 소켓이라 부른다. 이게 실행되기 위해서는 어느 클라이언트가 소켓을 만들고 tcp가 커넥션 셋업이 되어야 한다. 그럼 udp와 같이 요청을 내보내고 커넥션 소켓을 통해 요청을 읽고 응답하면 커넥션 소켓만을 닫고, 클라이언트 소켓은 응답을 받고 소켓을 닫는다.
위는 tcp 클라이언트의 예시이다. 역시 서버와 포트번호를 명시하고 소켓을 생성한다. 이후 서버네임과 포트번호를 적어 서버쪽 tcp와 커넥션을 맺는다. 이후 키보드로부터 입력을 받아들이고 클라이언트 소켓에 내보낼 데이터를 명시해 서버로 보낸다. 서버에서 응답이 오면 클라이언트 소켓이 이를 받아들이고 (modifiedsentence) 메세지를 올려보낸 후 클라이언트 소켓을 닫는다.
다음은 tcp 서버 프로세스다. 역시 서버 포트번호를 명시한 후 서버 소켓을 생성한다. 서버소켓을 생성하면 자동으로 운영체제와 ip주소와 포트번호를 할당한다. 그러면 그 서버소켓을 bind라는 함수를 통해서 프로그래머가 원하는 포트번호로 매핑을 시킨다. 이것이 이미 사용하는 포트번호면 실행되는 포트번호라는 메세지를 보내고 아니면 이것으로 포트번호를 결정한다. 그 다음 서버소켓.listen으로 클라이언트 요청이 들어올때까지 듣고 있는 것이다. 이후 서버는 준비가 됐다는 메세지를 출력하고 루프로 들어간다. 클라이언트의 커넥트 요청이 오면 그것을 받아들이고 그 결과를 가지고 새로운 커넥션 소켓을 생성한다. 커넥션 소켓의 포트번호는 12000이 아닌 새로운 포트번호고 프로그래머가 알 필요가 없다. addr는 클라이언트쪽 주소다. 역시 프로그래머가 알 필요가 없다. tcp 계층에서 이미 알기 때문에 자동 배달되기 때문이다. 이후 커넥션 소켓을 통해 이 내용을 받고 대문자로 바꿔 커넥션 소켓을 통해 클라이언트 소켓으로 보내고 소켓을 닫는다.
클라이언트 측에서 계속해서 입력을 받아 보내는 구조일 경우 소켓을 닫지 않고 계속 while루프에서 open하고 특별한 요청이 오면 커넥션 소켓을 닫게 할 수도 있다.