예제 소스
오목 좌표 LoRA: 15×15와 19×19 격자를 정확히 읽히기 · 파일 59개
tcpvlmclient.h
#pragma once
#include <QAtomicInt>
#include <QByteArray>
#include <QImage>
#include <QObject>
#include <QString>
class QTcpSocket;
/** 오목 판 PNG + 169바이트 격자 상태를 TCP로 보내 VLM 서버의 좌표 응답을 받습니다.
*
* 새 모드(persistent): 한 번 연결한 소켓을 게임/앱 수명 동안 계속 재사용합니다.
* 매 수마다 같은 소켓 위로 메시지를 보내고 응답을 받습니다. 서버도 한 클라이언트 연결을
* 루프로 계속 응대합니다.
*/
namespace TcpVlmClient {
/**
* QThread 위에 올려 두고 슬롯들을 QueuedConnection 으로 트리거합니다.
* 결과는 시그널로 메인 스레드에 전달됩니다.
*
* 모든 소켓 접근은 워커 스레드에서만 일어나도록 invokeMethod 로 디스패치하세요.
*/
class Worker : public QObject {
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
~Worker() override;
bool isBusy() const;
bool isConnected() const;
public slots:
/// 연결 보장(없으면 connect). 결과는 \ref pingReady (success, error) 로 emit.
void doPing(QString host, quint16 port, int timeoutMs);
/// 한 수 요청. ensureConnected 후 같은 소켓 위로 OMK3 송수신. 결과는 \ref moveReady.
/// boardSize: 13/15/19, aiSide: 1=Black, 2=White
void requestMove(QImage boardImage, QByteArray boardPacked, int boardSize, int aiSide,
QString host, quint16 port, int timeoutMs);
/// 학습용 기보 한 수를 *로깅 전용* 으로 서버에 전송 (추론 안 함).
/// stone:1=Black,2=White / actor:0=human,1=local_ai,2=vlm / mode/status: enum 정수.
void requestLog(int boardSize, int stone, int row, int col, int actor, int mode, int status,
int seq, QByteArray boardPacked, QString host, quint16 port, int timeoutMs);
/// 진행 중 요청을 가능한 빨리 중단하고 소켓을 닫는다. 다음 요청 때 재연결.
void cancel();
/// 명시적으로 소켓을 닫는다. (모드 변경/앱 종료 시)
void closeConnection();
signals:
void moveReady(bool success, int row, int col, QString errorMessage);
void pingReady(bool success, QString errorMessage);
/// 연결 상태 변화 알림 (UI 표시용).
void connectionStateChanged(bool connected, QString endpoint);
private:
bool ensureConnected(const QString &host, quint16 port, int timeoutMs, QString *errorOut);
bool readBytes(QByteArray *dst, qint64 nbytes, int deadlineMs);
bool writeAll(const QByteArray &data, int timeoutMs);
void closeSocketLocked(const QString &reason);
void emitConnState();
QTcpSocket *m_socket = nullptr;
QString m_curHost;
quint16 m_curPort = 0;
QAtomicInt m_cancel{0};
QAtomicInt m_busy{0};
};
} // namespace TcpVlmClient