본문 바로가기
컴퓨터 활용(한글, 오피스 등)/기타

10명의 사용자가 내부 네트워크에서 특정pc의 hsqldb에 정보를 저장하는 tcp/ip 프로그램

by 3604 2025. 9. 9.
728x90

 

 
 
 
10명의 사용자가 내부 네트워크를 통해 특정 PC의 HSQLDB에 정보를 저장하는 TCP/IP 프로그램을 구현하려면, 다음과 같은 구성 요소가 필요합니다.

✅ 전체 구조

[Client] x10 <--TCP/IP--> [Server] --> [HSQLDB (in-process or server mode)]

✅ 1. HSQLDB 설정 (서버 PC)

옵션 1: HSQLDB Server Mode (권장)

  • 여러 클라이언트가 동시에 접속 가능
  • server.properties 예시:
properties
复制
server.database.0=file:./mydb;user=sa;password=1234
server.dbname.0=mydb
server.port=9001
  • 실행 명령어:
bash
复制
java -cp hsqldb.jar org.hsqldb.server.Server

✅ 2. 서버 프로그램 (Java 예시)

java
复制
import java.io.*;
import java.net.*;
import java.sql.*;

public class DBServer {
    private static final String DB_URL = "jdbc:hsqldb:hsql://localhost:9001/mydb";

    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(5000)) {
            System.out.println("서버 대기 중...");

            while (true) {
                Socket client = serverSocket.accept();
                new ClientHandler(client).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class ClientHandler extends Thread {
        Socket client;

        ClientHandler(Socket client) {
            this.client = client;
        }

        public void run() {
            try (
                BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                Connection conn = DriverManager.getConnection(DB_URL, "sa", "1234")
            ) {
                String data = in.readLine();
                if (data == null) return;

                String[] parts = data.split(",");
                String name = parts[0];
                int age = Integer.parseInt(parts[1]);

                String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
                PreparedStatement stmt = conn.prepareStatement(sql);
                stmt.setString(1, name);
                stmt.setInt(2, age);
                stmt.executeUpdate();

                System.out.println("저장 완료: " + name);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

✅ 3. 클라이언트 프로그램 (Java 예시)

java
复制
import java.io.*;
import java.net.*;

public class DBClient {
    public static void main(String[] args) {
        String name = "홍길동";
        int age = 30;

        try (
            Socket socket = new Socket("192.168.0.100", 5000); // 서버 IP
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true)
        ) {
            out.println(name + "," + age);
            System.out.println("전송 완료");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

✅ 4. DB 테이블 생성 (최초 1회)

 
CREATE TABLE users (
    id INTEGER IDENTITY PRIMARY KEY,
    name VARCHAR(50),
    age INTEGER
);

✅ 5. 실행 순서

  1. HSQLDB 서버 실행 (server.properties 설정 후)
  2. DBServer.java 실행
  3. 10대의 PC에서 DBClient.java 실행 (또는 Python/C# 등으로 대체 가능)

✅ 6. 보안 및 안정성 고려사항

  • 내부 네트워크만 허용 (방화벽 설정)
  • TCP 포트 5000, 9001 개방
  • SQL 인젝션 방지 (PreparedStatement 사용)
  • 동시 접속 제한 (필요 시 세마포어 또는 큐 사용)

✅ 7. 다른 언어로의 전환

  • Python 클라이언트 가능:
Python
 
import socket
s = socket.socket()
s.connect(("192.168.0.100", 5000))
s.sendall("홍길동,30".encode())

필요하다면 Python 서버, C# 클라이언트, GUI, 로그 기록, 중복 확인 등도 추가해드릴 수 있습니다.
 
 
 
"10명의 사용자가 내부 네트워크에서 특정 PC의 HSQLDB에 정보를 저장하는 TCP/IP 프로그램(C++ Qt)" 


1. 개발 환경

  • Qt 6.5 이상 (Qt 5.15 도 가능)
  • JDK 11 이상
  • HSQLDB 2.7 서버 모드 (포트 9001, 별명 mydb, 계정 SA/1234)
  • hsqldb.jar 는 C:/hsqldb/hsqldb.jar 에 두고 진행

2. HSQLDB 서버 시작 스크립트 (start_hsqldb.bat)

bat
复制
rem start_hsqldb.bat
set JDK=%JAVA_HOME%\bin
set HSQL=C:\hsqldb
%JDK%\java -cp %HSQL%\hsqldb.jar org.hsqldb.server.Server ^
  --database.0 file:%HSQL%\data\mydb;user=sa;password=1234 ^
  --dbname.0 mydb --port 9001
실행 후 Server 1.7.2 is running on port 9001 메시지 확인

3. 테이블 생성 (최초 1회)

sql
复制
CREATE TABLE users (
  id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name VARCHAR(50),
  age INTEGER
);

4. Qt 프로젝트 파일 (TcpHsqlServer.pro)

pro
复制
QT       += core network sql
CONFIG   += console c++17
SOURCES  += main.cpp tcpserver.cpp dbwriter.cpp
HEADERS  += tcpserver.h dbwriter.h

5. 서버 소스 (한글 주석)

tcpserver.h
cpp
复制
#pragma once
#include <QTcpServer>
#include <QTcpSocket>

class DbWriter;
class TcpServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit TcpServer(QObject *parent = nullptr);
protected:
    void incomingConnection(qintptr socketDescriptor) override;
private:
    DbWriter *m_db;   // DB 삽입 담당 객체
};
tcpserver.cpp
cpp
复制
#include "tcpserver.h"
#include "dbwriter.h"

TcpServer::TcpServer(QObject *parent)
    : QTcpServer(parent), m_db(new DbWriter(this))
{
    listen(QHostAddress::AnyIPv4, 5000);   // 5000 포트 대기
    qInfo() << "TCP 서버가 5000 포트에서 대기 중...";
}

void TcpServer::incomingConnection(qintptr socketDescriptor)
{
    QTcpSocket *s = new QTcpSocket(this);
    s->setSocketDescriptor(socketDescriptor);

    // 클라이언트가 보낸 줄 단위 데이터를 읽어 DB 에 넣기
    connect(s, &QTcpSocket::readyRead, this, [=] {
        while (s->canReadLine()) {
            QByteArray line = s->readLine().trimmed();   // "Tom,25"
            m_db->insertUser(line);
        }
    });
    connect(s, &QTcpSocket::disconnected, s, &QTcpSocket::deleteLater);
}
dbwriter.h
cpp
复制
#pragma once
#include <QObject>
#include <QSqlDatabase>

class DbWriter : public QObject
{
    Q_OBJECT
public:
    explicit DbWriter(QObject *parent = nullptr);
    void insertUser(const QByteArray &csv);   // "이름,나이" 형식
};
dbwriter.cpp
cpp
复制
#include "dbwriter.h"
#include <QSqlQuery>
#include <QSqlError>

DbWriter::DbWriter(QObject *parent) : QObject(parent)
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QHSQL", "hsql-con");
    db.setHostName("localhost");
    db.setPort(9001);
    db.setDatabaseName("mydb");   // HSQLDB 별명
    db.setUserName("sa");
    db.setPassword("1234");
    if (!db.open())
        qFatal() << "HSQLDB 연결 실패:" << db.lastError().text();
    qInfo() << "HSQLDB 연결 성공";
}

void DbWriter::insertUser(const QByteArray &csv)
{
    QList<QByteArray> cols = csv.split(',');
    if (cols.size() != 2) return;

    QString name = QString::fromUtf8(cols[0]);
    int age = cols[1].toInt();

    QSqlQuery q(QSqlDatabase::database("hsql-con"));
    q.prepare("INSERT INTO users(name, age) VALUES (?, ?)");
    q.addBindValue(name);
    q.addBindValue(age);
    if (!q.exec())
        qWarning() << "삽입 오류:" << q.lastError().text();
    else
        qInfo() << "삽입 완료:" << name << age;
}
main.cpp
cpp
复制
#include <QCoreApplication>
#include "tcpserver.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    TcpServer srv;   // 서버 시작
    return a.exec();
}

6. 클라이언트 예제 (단일 파일)

cpp
复制
#include <QCoreApplication>
#include <QTcpSocket>
#include <QTest>   // for qSleep

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QTcpSocket sock;
    sock.connectToHost("192.168.0.100", 5000);   // 서버 IP
    if (!sock.waitForConnected(3000)) {
        qFatal("연결 실패");
    }

    QStringList names{"Alice","Bob","Cathy","Dave","Eve",
                      "Frank","Grace","Henry","Ivy","Jack"};
    for (int i = 0; i < 10; ++i) {
        QString msg = QString("%1,%2\n").arg(names[i]).arg(20 + i);
        sock.write(msg.toUtf8());
        sock.flush();
        QTest::qSleep(200);   // 0.2 초 간격
    }
    sock.waitForBytesWritten();
    qInfo() << "모든 데이터 전송 완료";
    return 0;
}

7. 빌드 & 실행 순서

  1. hsqldb.jar 경로를 시스템 CLASSPATH 에 추가
  2. qmake && cmake --build . --config Release (또는 Qt Creator 빌드)
  3. start_hsqldb.bat 실행 → 서버 프로세스 띄우기
  4. 서버 exe 실행
  5. 원하는 PC에서 클라이언트 exe 10대(또는 더 많이) 실행
  6. DBeaver 등으로 jdbc:hsqldb:hsql://localhost:9001/mydb 접속 → users 테이블 확인

8. 자주 발생하는 문제와 해결

  • QHSQL 드라이버 로드 실패
    → plugins/sqldrivers/qhsql.dll (또는 .so) 를 실행 파일 옆에 복사 & hsqldb.jar 가 CLASSPATH 에 있어야 함
  • 한글 깨짐
    → 클라이언트 toUtf8(), 서버 QString::fromUtf8() 로 통일, HSQLDB 기본 인코딩은 UTF-8
  • 포트 충돌
    → listen() 포트(5000) 또는 HSQLDB 포트(9001) 변경 후 사용
  • 다중 클라이언트 동시 접속
    → 위 코드는 Qt 신호/슬롯 기반 비동기 I/O 이므로 10명 동시 접속에도 문제 없음.
    대량 동시 삽입이 필요하면 DbWriter 내부에 큐 + 워커 스레드 추가 권장

이제 C++/Qt 로 작성된 TCP 서버가 10명(또는 그 이상)의 클라이언트로부터 데이터를 받아 HSQLDB 에 저장하는 전체 한글 설명이 완성되었습니다.
더 필요한 기능(GUI, 로그, 중복 확인 등)이 있으면 말씀해 주세요!
 
728x90