QT〃네트워크 정리

반응형



글쓰기에 앞서 QT카테고리는 아직 C++과 QT의 사용법이 익숙하지 않아 여러가지를 만들어 보며 두고두고 까먹지 않도록 메모할 목적으로 만들었습니다. 



현재 C++로 소켓통신을 만들 목적으로 공부중에 있고,

참고는 http://www.mrunix.de/forums/showthread.php?32189-Qt-Socket-Tutorial&s= 사이트에서 참고 했습니다.







m_socket = new QSocket(this);  
        QObject::connect(m_socket, SIGNAL(connected()), this, SLOT(slotConneted()));  
        QObject::connect(m_socket, SIGNAL(connectionClosed()), this, SLOT(slotDisconnected()));  
        QObject::connect(m_socket, SIGNAL(error(int)), this, SLOT(slotError(int)));  
        QObject::connect(m_socket, SIGNAL(readyRead()), this, SLOT(slotRead()));
cs


QT는 기본적으로 SIGNAL과 SLOT 형식을 많이 사용하기 때문에 SIGNAL-SlOT형식인 connect로 표현하면

1) SIGNAL : 연결이 들어오면 → SLOT : 연결을 한다.

2) SIGNAL : 연결을 끊으면 → SLOT : 연결을 끊는다.

3) SIGNAL : 에러가 생기면 → SLOT : 에러를 표시한다.

4) SIGNAL : 준비가 되면 → SLOT : 준비한다.


호스트에서는 




QString host = m_host->text();  
int port = m_port->value();  
m_socket -> connectToHost(host, port);

1) 호트트 연결 소스코드

2) QSocket은 ::connectToHost로 연결을 시작하고 그 후 즉시 반환합니다. 

3) 첫번째 파라미터는 지정 될 수 있는 IP 주소 또는 호스트 이름이 될 수 있습니다.











QString input = m_input->text();

if (input.isEmpty()) 
return;
 
if (m_socket->state() == QSocket::Connected)
{
    QTextStream stream(m_socket);
    stream << input << endl;
}


1) 이 소켓이 접속할것인지 소스코드..

2) 소켓을 통해 텍스트라인을 보낼지 여부를 확인합니다. 비어잇으면 그냥 리턴, 소켓이 연결되면 QTextStream을 거쳐 input으로 출력합니다.





QString text;
  while (m_socket->canReadLine())
  text += m_socket->readLine();

1) 연결 슬롯에 해당하는 코드

2) readyread 소켓의 접속 신호 . 이것은 항상 새로운 데이터가 전송되어 소켓에 도착되는 신호.








void ServerSocket::newConnection(int socketfd)
{
  QSocket* socket = new QSocket(parent());

  socket->setSocket(socketfd);

  emit newClient(socket);
}


1) 서버연결


class Client
{

public:
  Client(QSocket* socket, QListViewItem* item): m_socket(socket), m_item(item), m_num(++m_count)
 {

};
 
  ~Client() {
    delete m_socket;
    delete m_item;
  }
 
  inline QSocket* socket() { return m_socket; }
 
  inline QListViewItem* item() { return m_item; }
 
  inline int number() { return m_num; }
 
protected:
    static int m_count;
    QSocket* m_socket;
    QListViewItem* m_item;
    int m_num;

};


1) 헤더파일 에 해당하는 부분

2) 자동삭제는  m_clients.setAutoDelete (TRUE); 추가


void ServerMainWindow::sendToClients(const QString& text)
{
  if (text.isNull()) return;
 
  // iterate over all clients and send them the text
  QPtrDictIterator<Client> iter(m_clients);
  for (; iter.current() != 0++iter)
  {
    QSocket* sock = iter.current()->socket();
    QTextStream stream(sock);
    stream << text;
  }
}


1) 경로의 모든 항목을 해결하기 위해 반복자 사용시 코드 



   m_server = new ServerSocket(m_port->value(), this);
  if (!m_server->ok())
  {
    delete m_server;
    m_server = 0;
    return;
  }
 
  QObject::connect(m_server, SIGNAL(newClient(QSocket*)), this, SLOT(slotNewClient(QSocket*)));

1) 바인드() 호출이 성공하면 QServerSocket 함수는 ture를 반환 , 그렇지않으면 false


   QListViewItem* item = new QListViewItem(m_list, socket->peerAddress().toString(),
                                                  QString::number(socket->peerPort()));
  Client* client = new Client(socket, item);
 
  // notify all others about the newcomer
  sendToClients(QString("Server: Client %0 connected\n").arg(client->number()));
 
  m_clients.insert(socket, client);
 
  QObject::connect(socket, SIGNAL(connectionClosed()), this, SLOT(slotClientDisconnected()));
  QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(slotSocketRead()));
 
  // great the newcomer
  QTextStream stream(socket);
  stream << "Server: Hi\nYou are client " << client->number() << endl;

1) GUI에서 연결을 보여주는 리스트 뷰 항목을 만든다. 내부적으로 사용하는 경우 클라이언트 프로그램에서QSocket의 수신에 해당 슬롯으로 신호를 데이터 분리 처리 할 수 잇다. 링크 파트너는 그 자체로 연결이 종료되고, 단부에 소켓을 보내는 경우 연결이 종료 신호를 출력한다.


  QObject* sender = const_cast<QObject*>(QObject::sender());
  QSocket* socket = static_cast<QSocket*>(sender);
 
  qDebug("client disconnected");
 
  //disconnect signals
  socket->disconnect();
 
  // remove from dict
  Client* client = m_clients.take(socket);
 
  sendToClients(QString("Server: Client %0 disconnected\n").arg(client->number()));
 
  delete client;


1) 하나의 슬롯에 연결된 모든 클라이언트 소켓의 신호를 가지고 있기 때문에, 처음 발송 신호를 가지고 있는 소켓을 알아야 합니다.  QOBject를 통해 보낸사람을 알수 있다.

2) take()는 경로에서 엔트리를 삭제 하지 않고 자동삭제한다. 먼저 우리가 자동삭제를 허용했기 때문에 가능.

3) 수신 데이터가 클라이언트 프로그램과 유사하게 취급됨.



  QObject* sender = const_cast<QObject*>(QObject::sender());
  QSocket* socket = static_cast<QSocket*>(sender);
 
  Client* client = m_clients.find(socket);
 
  while (socket->canReadLine())
  {
    QString line = socket->readLine(); // read the line of text
 
    // and send it to everone including the sender
    sendToClients(QString("Client %0: %1").arg(client->number()).arg(line));
 
    client->item()->setText(2, line.left(line.length()-1));
    m_list->update();
  }


1) 이전과 같이 새로운데이터를 가지고 있는 소켓을 결정한다.

2) 다음 우리는 경로의 포인터를 사용하는 클라이언트를 대응하고

3) 인스턴스를 검색한다음 가능한 모든 라인을 읽고 현재를 포함한 모든 클라이언트에 보낸다. 



  QPtrDictIterator<Client> iter(m_clients);
  for (; iter.current() != 0++iter)
  {
    // disconnect the socket's signals from any slots or signals
    iter.current()->socket()->disconnect();
  }
 
  m_clients.clear(); // delete all clients (m_clients has autodelete ON)

1) 모든 클라이언트 객체를 삭제를 반복하고, 신호와 슬롯을 분리한다.

2) 마지막에 클라이언트 소멸자 연결 소켓이 연결이 종료되면 삭제한다.



-- 잠시 중단 --

나머지는 추후에 업데이트 하겠습니다.

반응형