socket — TCP 네트워크 연결 열기
socket — TCP 네트워크 연결 열기
프로그램이 네트워크를 통해 다른 컴퓨터와 통신해야 할 때 그 출발점이 되는 명령이 socket이에요. TCP 연결의 클라이언트 쪽을 열 수도 있고, 서버로 동작해 연결을 받아들일 수도 있어요. 반환된 채널 식별자를 read, puts, flush 등에 그대로 사용할 수 있어요.
출처: 문서
본문
문법
socket ?options? host port
socket -server command ?options? port
동작 방식
이 명령은 네트워크 소켓을 열고, 이후 read, puts, flush 같은 명령 호출에 사용할 수 있는 채널 식별자를 반환해요. 현재는 IPv4와 IPv6에서 TCP 네트워크 프로토콜만 지원돼요. -server 스위치가 지정됐는지에 따라 연결의 클라이언트 쪽 또는 서버 쪽을 여는 데 사용될 수 있어요.
참고로 모든 소켓의 기본 인코딩은 encoding system이 반환하는 시스템 인코딩이에요. 대부분의 경우 chan configure로 이걸 다른 것으로 바꿔야 하는데, 예를 들어 utf-8(다른 Tcl 프로세스와 통신하기에 이상적)이나 iso8859-1(많은 네트워크 프로토콜, 특히 오래된 것에 유용)로요.
클라이언트 소켓(CLIENT SOCKETS)
-server 옵션이 지정되지 않으면 연결의 클라이언트 쪽이 열리고, 읽기와 쓰기 모두에 사용할 수 있는 채널 식별자를 반환해요.
host와 port는 연결할 포트를 지정해요. 이 포트에서 연결을 받아들이는 서버가 있어야 해요. port는 정수 포트 번호(또는 호스트 운영체제가 지원하고 이해하는 곳에서는 서비스 이름)이고, host는 www.tcl.tk 같은 도메인 스타일 이름 또는 127.0.0.1이나 2001:DB8::1 같은 숫자 IPv4/IPv6 주소예요. localhost를 사용해 명령이 호출된 호스트를 가리킬 수 있어요.
연결에 대한 추가 정보를 지정하기 위해 host 앞에 다음 옵션이 올 수 있어요:
-myaddr addr— 연결에 사용할 클라이언트 쪽 네트워크 인터페이스의 도메인 스타일 이름 또는 숫자 IP 주소를 지정해요. 클라이언트 머신에 여러 네트워크 인터페이스가 있을 때 유용할 수 있어요. 생략하면 시스템 소프트웨어가 클라이언트 쪽 인터페이스를 선택해요.-myport port— 연결의 클라이언트 쪽에 사용할 정수 포트 번호(또는 서비스 이름)를 지정해요. 생략하면 시스템 소프트웨어가 클라이언트 포트 번호를 무작위로 선택해요.-async— 이 옵션은 클라이언트 소켓이 비동기로 연결되게 해요. 즉 소켓이 즉시 만들어지지만,socket호출이 반환될 때 서버에 아직 연결되지 않았을 수 있어요.
연결 시도가 성공하거나 실패하기 전에 소켓에서 gets나 flush를 수행할 때, 소켓이 블로킹 모드면 연산은 연결이 완료되거나 실패할 때까지 기다려요. 논블로킹 모드면 연산은 즉시 반환되고 소켓의 fblocked가 1을 반환해요. 동기 클라이언트 소켓은 (연결된 후에) 이를 통해 비동기 모드로 전환될 수 있어요:
chan configure chan -blocking 0
비동기 연결이 진행되는 동안 Tcl 이벤트 루프가 실행 중이어야 해요. 백그라운드에서 여러 번의 연결 시도를 해야 할 수 있기 때문이에요. 이벤트 루프를 실행하면 소켓에 쓰기 가능 채널 이벤트를 설정해 비동기 연결이 성공했는지 실패했는지 통지를 받을 수도 있어요.
chan configure의 -connecting 옵션으로 연결이 여전히 진행 중인지 확인할 수 있어요. 성공적인 연결을 검증하려면 -connecting이 0을 반환할 때 -error 옵션을 확인하면 돼요. 이벤트 큐 없이 동작할 경우 지금은 내부 상태 머신을 진행시키기 위한 chan configure 호출이 필요해요.
서버 소켓(SERVER SOCKETS)
-server 옵션이 지정되면 새 소켓은 주어진 포트에서 수신하는 서버가 돼요 (정수 또는 서비스 이름; port가 0이면 운영체제가 서버 소켓에 빈 포트를 할당하는데, chan configure로 -sockname 옵션을 읽어 알아낼 수 있어요). 호스트가 IPv4와 IPv6를 모두 지원하면 소켓은 두 주소 계열 모두에서 수신해요. Tcl은 주어진 포트로의 연결을 자동으로 받아들여요.
각 연결마다 Tcl은 클라이언트와 통신하는 데 사용할 수 있는 새 채널을 만들어요. 그런 다음 Tcl은 세 개의 추가 인자, 즉 새 채널의 이름, 클라이언트 호스트의 네트워크 주소 표기법으로 된 주소, 클라이언트의 포트 번호로 command(적절히 명령 프리픽스 리스트)를 호출해요.
port 앞에 다음 추가 옵션을 지정할 수 있어요:
-myaddr addr— 연결에 사용할 서버 쪽 네트워크 인터페이스의 도메인 스타일 이름 또는 숫자 IP 주소를 지정해요. 서버 머신에 여러 네트워크 인터페이스가 있을 때 유용할 수 있어요. 생략하면 서버 소켓이 와일드카드 주소에 바인딩돼 어떤 인터페이스에서든 연결을 받아들일 수 있어요.addr이 로컬 머신에서 사용 가능한 여러 IP 주소로 해석되는 도메인 이름이면 소켓은 모두에서 수신해요.
서버 채널은 입력이나 출력에 사용할 수 없어요. 그 유일한 용도는 새 클라이언트 연결을 받아들이는 거예요. 각 수신 클라이언트 연결을 위해 만들어진 채널은 입력과 출력 모두로 열려 있어요. 서버 채널을 닫으면 서버가 종료되어 새 연결을 받아들이지 않지만, 기존 연결은 영향을 받지 않아요.
서버 소켓은 새 연결이 열리는 시점을 알아내기 위해 Tcl 이벤트 메커니즘에 의존해요. 애플리케이션이 예를 들어 vwait 명령을 호출하거나 C 프로시저 Tcl_DoOneEvent를 호출해 이벤트 루프에 들어가지 않으면 어떤 연결도 받아들이지 않아요.
port가 0으로 지정되면 운영체제가 서버 소켓에 사용하지 않는 포트를 할당해요. 실제로 할당된 포트 번호는 아래에 설명한 대로 chan configure 명령으로 -sockname 옵션을 검색해 만들어진 서버 소켓에서 알아낼 수 있어요.
구성 옵션(CONFIGURATION OPTIONS)
chan configure 명령으로 소켓 채널의 여러 읽기 전용 구성 옵션을 질의할 수 있어요:
-error— 주어진 소켓의 현재 오류 상태를 가져와요. 비동기 연결 연산이 성공했는지 결정해야 할 때 유용해요. 오류가 있었다면 오류 메시지가 반환되고, 없었다면 빈 문자열이 반환돼요. 오류 상태는 읽기 연산에 의해 재설정되는데, 이것은 밑에 있는getsockopt(SO_ERROR)호출을 모방한 것이에요.-sockname— 클라이언트 소켓(클라이언트가 서버 소켓에 연결될 때 만들어지는 채널 포함)의 경우 이 옵션은 세 요소 리스트, 즉 소켓의 주소, 호스트 이름, 포트 번호를 반환해요. 호스트 이름을 계산할 수 없으면 두 번째 요소가 첫 요소인 주소와 동일해요. 서버 소켓의 경우 이 옵션은 3의 배수 요소 리스트를 각각 위에서 설명한 것과 같은 의미로 반환해요. 서버 소켓이-myaddr없이 만들어졌거나-myaddr인자가 호출 호스트에 로컬인 여러 IP 주소로 해석되는 도메인 이름인 경우 리스트에 둘 이상의 그룹이 포함돼요.-peername— 서버 소켓에서는 지원되지 않아요. 클라이언트 및 수락된 소켓의 경우 이 옵션은 세 요소 리스트를 반환하는데, 피어 소켓이 연결되거나 바인딩된 주소, 호스트 이름, 포트예요. 호스트 이름을 계산할 수 없으면 리스트의 두 번째 요소가 그 첫 요소인 주소와 동일해요.-connecting— 서버 소켓에서는 지원되지 않아요. 클라이언트 소켓의 경우 비동기 연결이 여전히 진행 중이면 1, 그렇지 않으면 0을 반환해요.
예제
아주 간단한 시간 서버:
proc Server {startTime channel clientaddr clientport} {
puts "Connection from $clientaddr registered"
set now [clock seconds]
puts $channel [clock format $now]
puts $channel "[expr {$now - $startTime}] since start"
close $channel
}
socket -server [list Server [clock seconds]] 9900
vwait forever
서버와 통신하고 정보를 추출하는 대응 클라이언트:
set server localhost
set sockChan [socket $server 9900]
gets $sockChan line1
gets $sockChan line2
close $sockChan
puts "The time on $server is $line1"
puts "That is [lindex $line2 0]s since the server started"
역사
IPv6 지원은 Tcl 8.6에서 추가됐어요.
더 알아보기
chan: 채널 구성 및 옵션flush,open,read: 채널 I/O