python chatting
Stomp
사용하여 처리
websocket-client 라이브러리만으로는 Stomp 지원이 부족하기 때문에 stomp.py 라이브러리를 사용
pip install stomp.py
import stomp
import time
class MyListener(stomp.ConnectionListener):
def on_error(self, frame):
print(f"Received an error: {frame.body}")
def on_message(self, frame):
print(f"Received a message: {frame.body}")
# WebSocket 주소 및 엔드포인트 설정
server_url = 'chatting.linkerbiz.net'
chat_room_id = '1234' # 실제 사용하려는 채팅방 ID로 대체
destination = f'/topic/public.{chat_room_id}'
send_destination = f'/app/chat.sendMessage.{chat_room_id}'
# STOMP 클라이언트 설정
conn = stomp.Connection12([(server_url, 61614)], auto_content_length=False)
conn.set_listener('', MyListener())
conn.connect(wait=True)
# 메시지 전송
message = {
'type': 'chat',
'content': 'Hello from Python client!',
'sender': 'python_user'
}
conn.send(body=str(message), destination=send_destination)
# 메시지 구독
conn.subscribe(destination=destination, id=1, ack='auto')
# 연결 유지
time.sleep(10) # 10초 동안 대기 (필요한 만큼 대기 시간을 설정)
conn.disconnect()
##번외
웹소켓 연결 테스트
npm install -g wscat
wscat -c ws://localhost:20118/ws
## 에러원인
registry.addEndpoint("/ws")
.addInterceptors(new WebSocketHandshakeInterceptor())
.setAllowedOrigins("*")
.setAllowedOrigins("http://localhost:3000",
"https://chatting.linkerbiz.net",
"https://main-api.linkerbiz.net",
"http://localhost"); // 허용할 출처
// .withSockJS();파이썬에서는 호환이 안된다. SockJS…
## Full code
import websocket
import stomper
import queue
import threading
ws_uri = "ws://{}:{}/ws-python"
class StompClient(object):
"""Class containing methods for the Client."""
def __init__(self, jwt_token, server_ip="localhost", port_number=20118, destinations=[]):
self.NOTIFICATIONS = queue.Queue()
self.destinations = destinations
self.ws_uri = ws_uri.format(server_ip, port_number)
self.headers = {
"content-type": "application/json",
'accept-version': '1.1,1.2',
'Connection': 'Upgrade',
'Upgrade': 'websocket',
'Sec-WebSocket-Key': 'XLjN9Xx3g/5UM5wKQJwNng==',
'Sec-WebSocket-Version': '13'
}
self.ws = None # WebSocket 인스턴스를 저장할 변수
self.thread = None # WebSocket thread
def on_open(self, ws):
"""
Handler when a websocket connection is opened.
"""
# Initial CONNECT required to initialize the server's client registries.
connect_message = "CONNECT\naccept-version:1.0,1.1,2.0\n\n\x00"
ws.send(connect_message)
# Subscribing to all required destinations
for destination in self.destinations:
sub = stomper.subscribe(destination, "linker_python_desktop01", ack="auto")
ws.send(sub)
def on_message(self, ws, message):
"""
Handler for receiving a message.
"""
print(f"Message received: {message}")
# Try to process the message as a STOMP frame
try:
# Unpack the message using stomper
unpacked_msg = stomper.unpack_frame(message)
print("Received the message: " + str(unpacked_msg))
self.add_notifications(unpacked_msg)
except Exception as e:
print(f"Failed to unpack message: {e}")
def on_error(self, ws, error):
"""
Handler when an error is raised.
"""
print(f"Error: {error}")
def on_close(self, ws, close_status_code, close_msg):
"""
Handler when a websocket is closed.
"""
print(f"The websocket connection is closed with status: {close_status_code}, reason: {close_msg}")
def create_connection(self):
"""
Method which starts the long-term websocket connection in a separate thread.
"""
self.ws = websocket.WebSocketApp(self.ws_uri,
header=self.headers,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close)
self.ws.on_open = self.on_open
# Create a new thread to run the WebSocket
self.thread = threading.Thread(target=self.run_forever)
self.thread.daemon = True # Thread dies when the main thread exits.
self.thread.start()
def run_forever(self):
"""Helper method to run WebSocket forever."""
self.ws.run_forever()
def add_notifications(self, msg):
"""
Method to add a message to the websocket queue.
"""
self.NOTIFICATIONS.put(msg)
def send_message(self, message, chat_room_id):
"""
Method to send a message to the server.
"""
send_destination = f"/app/chat.sendMessage.{chat_room_id}"
headers = {
"destination": send_destination,
"content-type": "application/json" # 명시적으로 JSON 설정
}
# Build the STOMP SEND frame
# stomp_message = stomper.send(send_destination, message, headers)
stomp_frame = (
f"SEND\n"
f"destination:{send_destination}\n"
f"content-type:application/json\n\n"
f"{message}\x00"
)
# Send the message over WebSocket
if self.ws:
self.ws.send(stomp_frame)
print(f"Sent message to {send_destination}: {message}")
else:
print("WebSocket is not connected.")


