1.新建qt空项目
2.———————*.pro———————–
INCLUDEPATH += /usr/include/gtk-3.0 /usr/include/at-spi2-atk/2.0 /usr/include/at-spi-2.0 /usr/include/dbus-1.0 /usr/lib/x86_64-linux-gnu/dbus-1.0/include /usr/include/gtk-3.0 /usr/include/gio-unix-2.0 /usr/include/cairo /usr/include/pango-1.0 /usr/include/harfbuzz /usr/include/pango-1.0 /usr/include/fribidi /usr/include/harfbuzz /usr/include/atk-1.0 /usr/include/cairo /usr/include/pixman-1 /usr/include/uuid /usr/include/freetype2 /usr/include/gdk-pixbuf-2.0 /usr/include/libpng16 /usr/include/x86_64-linux-gnu /usr/include/libmount /usr/include/blkid /usr/include/glib-2.0 /usr/lib/x86_64-linux-gnu/glib-2.0/include
LIBS += -pthread -pthread -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0
SOURCES += \
main.cpp
3.————————–main.cpp——————–
#include
#include
#include
#include
#include
#include
// 全局变量
static gboolean server_running = FALSE;
static GList *client_threads = NULL; // 保存客户端线程信息
// 服务器结构体
typedef struct {
int server_socket;
GtkListStore *client_list; // 修改为 GtkListStore* 类型
} ServerData;
// 客户端信息结构体
typedef struct {
int socket;
pthread_t thread;
int cpu;
} ClientInfo;
// 更新UI列表显示
static gboolean update_client_list(GtkWidget *list, gpointer data) {
gtk_list_store_clear(GTK_LIST_STORE(data));
GList *node;
for (node = client_threads; node; node = node->next) {
ClientInfo *info = (ClientInfo *)node->data;
char buffer[256];
snprintf(buffer, sizeof(buffer), “Client %d on CPU %d”, info->socket, info->cpu);
GtkListStore *store = GTK_LIST_STORE(data);
GtkTreeIter iter;
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, buffer, -1);
}
return FALSE;
}
// 客户端处理线程函数
void *client_handler(void *arg) {
ClientInfo *client_info = (ClientInfo *)arg;
int client_socket = client_info->socket;
// 获取线程运行在哪个CPU
cpu_set_t cpuset;
pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
for (int cpu = 0; cpu < CPU_SETSIZE; cpu++) {
if (CPU_ISSET(cpu, &cpuset)) {
client_info->cpu = cpu;
break;
}
}
char buffer[256];
while (1) {
ssize_t len = recv(client_socket, buffer, sizeof(buffer) – 1, 0);
if (len <= 0) {
break;
}
buffer[len] = '\0';
g_print("Received from client %d: %s\n", client_socket, buffer);
// 回显消息
send(client_socket, buffer, len, 0);
}
close(client_socket);
client_threads = g_list_remove(client_threads, client_info);
g_idle_add((GSourceFunc)update_client_list, gtk_tree_view_get_model(GTK_TREE_VIEW(arg)));
free(client_info);
return NULL;
}
// 服务器监听线程函数
void *server_thread(void *arg) {
ServerData *server_data = (ServerData *)arg;
int server_socket = server_data->server_socket;
while (server_running) {
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &addr_len);
if (client_socket < 0) {
break;
}
ClientInfo *client_info = g_new0(ClientInfo, 1);
client_info->socket = client_socket;
pthread_create(&client_info->thread, NULL, client_handler, client_info);
client_threads = g_list_append(client_threads, client_info);
g_idle_add((GSourceFunc)update_client_list, server_data->client_list);
}
return NULL;
}
// 启动服务器
static void start_server(GtkButton *button, ServerData *data) {
if (server_running) {
return;
}
server_running = TRUE;
struct sockaddr_in server_addr;
data->server_socket = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(12345);
bind(data->server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
listen(data->server_socket, 5);
pthread_t server_tid;
pthread_create(&server_tid, NULL, server_thread, data);
gtk_button_set_label(button, “Stop Server”);
}
// 停止服务器
static void stop_server(GtkButton *button, ServerData *data) {
if (!server_running) {
return;
}
server_running = FALSE;
close(data->server_socket);
gtk_button_set_label(button, “Start Server”);
}
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), “GTK TCP Server”);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
g_signal_connect(window, “destroy”, G_CALLBACK(gtk_main_quit), NULL);
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add(GTK_CONTAINER(window), vbox);
GtkWidget *button = gtk_button_new_with_label(“Start Server”);
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
GtkWidget *scrolled_win = gtk_scrolled_window_new(NULL, NULL);
gtk_box_pack_start(GTK_BOX(vbox), scrolled_win, TRUE, TRUE, 0);
// 创建 GtkListStore 用于存储客户端列表
GtkListStore *list_store = gtk_list_store_new(1, G_TYPE_STRING);
// 创建 GtkTreeView,并将 GtkListStore 设为其数据模型
GtkWidget *tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree_view), -1, “Clients”, gtk_cell_renderer_text_new(), “text”, 0, NULL);
// 将 GtkTreeView 添加到滚动窗口
gtk_container_add(GTK_CONTAINER(scrolled_win), tree_view);
// 将 GtkListStore 传递给 ServerData
ServerData server_data = {0, list_store}; // 正确的类型传递
g_signal_connect(button, “clicked”, G_CALLBACK(start_server), &server_data);
gtk_widget_show_all(window);
gtk_main();
return 0;
}