使用 gtkmm3 的套接字服务器

Socket server using gtkmm3

本文关键字:服务器 套接字 gtkmm3 使用      更新时间:2023-10-16

我正在尝试制作一个GUI,当用户按下按钮时将连接到网络。我在尝试编译gui_ex.cpp文件时遇到编译错误。

gui_ex.cpp: In member function ‘void Gui_Ex::on_connect()’:
gui_ex.cpp:110:19: error: no matching function for call to ‘Gui_Ex::close(int&)’
         close(sock);
                   ^
gui_ex.cpp:110:19: note: candidate is:
In file included from /usr/include/gtkmm-3.0/gtkmm/dialog.h:30:0,
                 from /usr/include/gtkmm-3.0/gtkmm/aboutdialog.h:33,
                 from /usr/include/gtkmm-3.0/gtkmm.h:99,
                 from gui_ex.h:4,
                 from gui_ex.cpp:1:
/usr/include/gtkmm-3.0/gtkmm/window.h:2026:8: note: void Gtk::Window::close()
   void close();
        ^
/usr/include/gtkmm-3.0/gtkmm/window.h:2026:8: note:   candidate expects 0 arguments, 1 provided
gui_ex.cpp:117:19: error: no matching function for call to ‘Gui_Ex::close(int&)’
         close(sock);
                   ^
gui_ex.cpp:117:19: note: candidate is:
In file included from /usr/include/gtkmm-3.0/gtkmm/dialog.h:30:0,
                 from /usr/include/gtkmm-3.0/gtkmm/aboutdialog.h:33,
                 from /usr/include/gtkmm-3.0/gtkmm.h:99,
                 from gui_ex.h:4,
                 from gui_ex.cpp:1:
/usr/include/gtkmm-3.0/gtkmm/window.h:2026:8: note: void Gtk::Window::close()
   void close();
        ^
/usr/include/gtkmm-3.0/gtkmm/window.h:2026:8: note:   candidate expects 0 arguments, 1 provided

似乎程序在套接字的关闭命令和 Gtk::窗口的关闭命令之间混淆了。是否可以调整代码,以便编译器可以区分两者?

这是我的代码:gui_ex.h 文件

#ifndef GTKMM_EX_GUI_H
#define GTKMM_EX_GUI_H
#include <gtkmm.h>
class Gui_Ex : public Gtk::Window
{
public:
    Gui_Ex();
    virtual ~Gui_Ex();
protected:
    // Signal handlers:
    // new button
    void on_connect();
  void on_spin();
  //void on_spinbutton_digits_changed();
    //child widgets
  //Gtk::Frame m_Frame_Init, m_Frame_Control;
  Glib::RefPtr<Gtk::Adjustment> m_adjustment;
  Gtk::Label m_label;
  Gtk::Grid m_grid;
  Gtk::SpinButton m_spin;
    Gtk::Button m_button2, m_button3; //m_connect;

};
#endif // GTKMM_EX_GUI_H

gui_ex.cpp

#include "gui_ex.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>
#include <string.h> // memset
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <vector>
#include <string>
using namespace std;
#define PORT "8888"
//#define BACKLOG 2
#define IP_ADDR "192.168.137.99"
#define MAXLEN 1024
int BACKLOG =0;
static unsigned int cli_count = 0;
static int uid = 20;
vector<int> cliarray;
Gui_Ex::Gui_Ex()
:
  // m_button1("Button 1"),
   m_adjustment( Gtk::Adjustment::create(1.0, 1.0, 5.0, 1.0, 5.0, 0.0) ),
   m_button2("Enter"),
   m_button3("Connect"),
   m_spin(m_adjustment),
   m_label("Choose # clients")

{
    set_title("Grid");
  set_border_width(12);

  m_grid.attach(m_label, 0,0,1,1); //column, row, width (# col span), height (# row span)
  m_grid.attach(m_spin, 1,0,1,1);
  m_spin.set_wrap();
  m_spin.set_numeric(true);
  m_grid.attach(m_button2, 2,0,1,1);
  m_grid.attach(m_button3, 0,1,3,1);
  m_button3.set_sensitive(false);
  m_button2.signal_clicked().connect(sigc::mem_fun(*this, &Gui_Ex::on_spin));
  m_button3.signal_clicked().connect(sigc::mem_fun(*this, &Gui_Ex::on_connect));
  //m_button3.signal_clicked().connect(sigc::bind<int>(sigc::mem_fun(*this, &Gui_Ex::on_connect), m_spin.get_value_as_int()));  
  add(m_grid);
  m_grid.show_all();
  //show_all_children();
}
Gui_Ex::~Gui_Ex()
{
}

void Gui_Ex::on_spin()
{
  cout<<"Spin value =: " << m_spin.get_value_as_int() << endl;
  BACKLOG = m_spin.get_value_as_int();
  m_spin.set_sensitive(false);
  m_button2.set_sensitive(false);
  m_button3.set_sensitive(true);
}
void Gui_Ex::on_connect()
{
    int connfd =0, n = 0;
    int *new_sock, sock;
    cout << BACKLOG << endl;
    pthread_t thread;
    struct addrinfo hints, *res;
    int reuseaddr = 1; // True 
    // Get the address info 
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    if (getaddrinfo(IP_ADDR, PORT, &hints, &res) != 0) {
        perror("getaddrinfo");
        //return 1;
    }
    // Create the socket 
    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (sock == -1) {
        perror("socket");
       // return 1;
    }
    // Enable the socket to reuse the address 
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1) {
        perror("setsockopt");
        close(sock);
       // return 1;
    }
    // Bind to the address 
    if (bind(sock, res->ai_addr, res->ai_addrlen) == -1) {
        perror("bind");
        close(sock);
        //return 0;
    }
    freeaddrinfo(res);
    // Listen 
    if (listen(sock, BACKLOG) == -1) {
        perror("listen");
       // return 0;
    }
    cout << "listening for connections" << endl;
    // Main loop 
    bool running = true;
    // Initialize clients 
    while (running)
    {  
      size_t size = sizeof(struct sockaddr_in);
      struct sockaddr_in their_addr;
      int clilen = sizeof(their_addr);
      int newsock = accept(sock, (struct sockaddr*)&their_addr, &size);
      if (newsock == -1) 
      {
        perror("accept");
       // return -1;
      }
      cli_count++;
      printf("Got a connection from %s on port %dn", inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port));
      cliarray.push_back(newsock);
      if (cli_count == BACKLOG)
      {
         cout << "Max clients reached" << endl;
        running = false;
        break;
      }
    }
}

你只需要在这里显式调用全局命名空间。也就是说,当尝试在 libc 中调用 close 函数而不是基类的 close 方法时,应在前面加上全局命名空间指示符:

::close(sock);

基本上,对象命名空间中存在 close 方法会隐藏同名的全局符号。有关更全面的解释,请参阅此处的第一个答案:全局范围与全局命名空间