콘텐츠로 이동

WebSocket 클라이언트

서버와의 실시간 양방향 통신을 위한 WebSocket 클라이언트.

local websocket = require("websocket")
local client, err = websocket.connect("wss://api.example.com/ws")
if err then
return nil, err
end
local client, err = websocket.connect("wss://api.example.com/ws", {
headers = {
["Authorization"] = "Bearer " .. token
},
protocols = {"graphql-ws"},
dial_timeout = "10s",
read_timeout = "30s",
compression = websocket.COMPRESSION.CONTEXT_TAKEOVER
})
파라미터타입설명
urlstringWebSocket URL (ws:// 또는 wss://)
optionstable연결 옵션 (선택적)

반환: Client, error

옵션타입설명
headerstable핸드셰이크용 HTTP 헤더
protocolstableWebSocket 서브프로토콜
dial_timeoutnumber/string연결 타임아웃 (ms 또는 “5s”)
read_timeoutnumber/string읽기 타임아웃
write_timeoutnumber/string쓰기 타임아웃
compressionnumber압축 모드 (상수 참조)
compression_thresholdnumber압축 최소 크기 (0-100MB)
read_limitnumber최대 메시지 크기 (0-128MB)
channel_capacitynumber수신 채널 버퍼 (1-10000)

타임아웃 형식: 숫자는 밀리초, 문자열은 Go duration 형식 (“5s”, “1m”)을 사용합니다.

local ok, err = client:send("Hello, Server!")
if err then
return nil, err
end
-- JSON 전송
client:send(json.encode({
type = "subscribe",
channel = "orders"
}))
client:send(binary_data, websocket.BINARY)
파라미터타입설명
datastring메시지 내용
typenumberwebsocket.TEXT (1) 또는 websocket.BINARY (2)

반환: boolean, error

client:ping()

반환: boolean, error

channel() 메서드는 메시지 수신을 위한 채널을 반환합니다. receive()channel()의 별칭입니다. 멀티플렉싱을 위해 channel.select와 함께 작동합니다.

local ch = client:channel()
local msg, ok = ch:receive()
if ok then
print("Type:", msg.type) -- "text" 또는 "binary"
print("Data:", msg.data)
end
local ch = client:channel()
while true do
local msg, ok = ch:receive()
if not ok then
break -- 연결 닫힘
end
if msg.type == "text" then
local data = json.decode(msg.data)
handle_message(data)
end
end
local ch = client:channel()
local timeout = time.after("30s")
while true do
local r = channel.select {
ch:case_receive(),
timeout:case_receive()
}
if r.channel == timeout then
client:ping() -- Keep-alive
timeout = time.after("30s")
else
local data = json.decode(r.value.data)
process(data)
end
end
필드타입설명
typestring"text" 또는 "binary"
datastring?메시지 내용(알 수 없는 페이로드 타입의 경우 nil)
-- 정상 닫기 (코드 1000)
client:close()
-- 코드와 이유와 함께
client:close(websocket.CLOSE_CODES.NORMAL, "Session ended")
-- 에러 닫기
client:close(websocket.CLOSE_CODES.INTERNAL_ERROR, "Processing failed")
파라미터타입설명
codenumber닫기 코드 (1000-4999), 기본값 1000
reasonstring닫기 이유 (선택적)

반환: boolean, error

-- 숫자 (send용)
websocket.TEXT -- 1
websocket.BINARY -- 2
-- 문자열 (수신된 메시지 type 필드)
websocket.TYPE_TEXT -- "text"
websocket.TYPE_BINARY -- "binary"
websocket.TYPE_PING -- "ping"
websocket.TYPE_PONG -- "pong"
websocket.TYPE_CLOSE -- "close"
websocket.COMPRESSION.DISABLED -- 0 (압축 없음)
websocket.COMPRESSION.CONTEXT_TAKEOVER -- 1 (슬라이딩 윈도우)
websocket.COMPRESSION.NO_CONTEXT -- 2 (메시지별)
상수코드설명
NORMAL1000정상 종료
GOING_AWAY1001서버 종료 중
PROTOCOL_ERROR1002프로토콜 에러
UNSUPPORTED_DATA1003지원되지 않는 데이터 타입
RESERVED1004예약됨
NO_STATUS1005상태 수신되지 않음
ABNORMAL_CLOSURE1006연결 끊김
INVALID_PAYLOAD1007잘못된 프레임 페이로드
POLICY_VIOLATION1008정책 위반
MESSAGE_TOO_BIG1009메시지 너무 큼
MANDATORY_EXTENSION1010필수 확장이 협상되지 않음
INTERNAL_ERROR1011서버 에러
SERVICE_RESTART1012서버 재시작 중
TRY_AGAIN_LATER1013서버 과부하
BAD_GATEWAY1014게이트웨이 에러
TLS_HANDSHAKE1015TLS 핸드셰이크 실패
client:close(websocket.CLOSE_CODES.NORMAL, "Done")
local function connect_chat(room_id, on_message)
local client, err = websocket.connect("wss://chat.example.com/ws", {
headers = {["Authorization"] = "Bearer " .. token}
})
if err then
return nil, err
end
-- 방 참여
client:send(json.encode({
type = "join",
room = room_id
}))
-- 메시지 루프
local ch = client:channel()
while true do
local msg, ok = ch:receive()
if not ok then break end
local data = json.decode(msg.data)
on_message(data)
end
client:close()
end
local client = websocket.connect("wss://stream.example.com/prices")
client:send(json.encode({
action = "subscribe",
symbols = {"BTC-USD", "ETH-USD"}
}))
local ch = client:channel()
local heartbeat = time.after("30s")
while true do
local r = channel.select {
ch:case_receive(),
heartbeat:case_receive()
}
if r.channel == heartbeat then
client:ping()
heartbeat = time.after("30s")
elseif not r.ok then
break -- 연결 닫힘
else
local price = json.decode(r.value.data)
update_price(price.symbol, price.value)
end
end
client:close()

WebSocket 연결은 보안 정책 평가 대상입니다.

액션리소스설명
websocket.connect-WebSocket 연결 허용/거부
websocket.connect.urlURL특정 URL 연결 허용/거부

정책 설정은 보안 모델을 참조하세요.

조건종류재시도 가능
연결 비활성화됨errors.PERMISSION_DENIED아니오
URL 허용되지 않음errors.PERMISSION_DENIED아니오
컨텍스트 없음errors.INTERNAL아니오
연결 실패errors.INTERNAL
잘못된 연결 IDerrors.INTERNAL아니오
local client, err = websocket.connect(url)
if err then
if errors.is(err, errors.PERMISSION_DENIED) then
print("Access denied:", err:message())
elseif err:retryable() then
print("Temporary error:", err:message())
end
return nil, err
end

에러 처리는 에러 처리를 참조하세요.