我試圖從頭開始重新創建一個GUI工作,它將成爲我的第一個網絡應用程序。爲此,我一直在閱讀所有可以找到的C/C++套接字教程信息,但我已經用自己的信息將自己編碼爲無用的幾百行代碼。基本的C++套接字客戶端
有兩個問題(據我所知),用下面的代碼:
1)當它連接到我應該被偵聽的端口,就應該立即收到字符串99999999%connect
。此時,我應該能夠發送0
並開始接收當天數據的開始。但是,我沒有收到第一條消息。
2)我不知道如何在這樣一種方式,它不會導致GTK UI鎖住寫這個。我知道,這是一些基本的東西,但是這整個事情只是在套接字上進行的第一次嘗試。
總之,這裏的代碼:
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <gtk/gtk.h>
#define UNUSED(x) (void) x
typedef struct
{
GtkWidget *window, *grid,
*labelHost, *labelPort, *textFieldHost, *textFieldPort,
*buttonConnect;
}uiWidgets;
int sockfd = 0;
gboolean on_close_cleanup();
void buttonConnect_on_clicked(GtkButton *button, uiWidgets* widgets);
void connect_to_logview(struct addrinfo *hostname_result);
void listen_for_logview();
int main()
{
uiWidgets widgets;
gtk_init(NULL, NULL);
widgets.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(widgets.window), "SG GUI V3.00");
g_signal_connect(widgets.window, "destroy", gtk_main_quit, nullptr);
g_signal_connect(widgets.window, "delete-event", G_CALLBACK(on_close_cleanup),
nullptr);
widgets.labelHost = gtk_label_new("Host");
widgets.labelPort = gtk_label_new("Port");
widgets.textFieldHost = gtk_entry_new();
widgets.textFieldPort = gtk_entry_new();
widgets.buttonConnect = gtk_button_new_with_label("Connect");
g_signal_connect(widgets.buttonConnect, "clicked",
G_CALLBACK(buttonConnect_on_clicked),
&widgets);
widgets.grid = gtk_grid_new();
gtk_grid_set_row_spacing(GTK_GRID(widgets.grid), 5);
gtk_grid_set_column_homogeneous(GTK_GRID(widgets.grid), true);
gtk_grid_set_row_homogeneous(GTK_GRID(widgets.grid), true);
gtk_grid_attach(GTK_GRID(widgets.grid), widgets.labelHost, 0, 0, 1, 1);
gtk_grid_attach(GTK_GRID(widgets.grid), widgets.labelPort, 2, 0, 1, 1);
gtk_grid_attach(GTK_GRID(widgets.grid), widgets.textFieldHost, 0, 1, 2, 1);
gtk_grid_attach(GTK_GRID(widgets.grid), widgets.textFieldPort, 2, 1, 1, 1);
gtk_grid_attach(GTK_GRID(widgets.grid), widgets.buttonConnect, 1, 2, 1, 1);
gtk_container_add(GTK_CONTAINER(widgets.window), widgets.grid);
gtk_widget_show_all(widgets.window);
gtk_main();
return 0;
}
gboolean on_close_cleanup()
{
close(sockfd);
return false;
}
void buttonConnect_on_clicked(GtkButton *button, uiWidgets* widgets)
{
UNUSED(button);
struct addrinfo hints, *hostname_result;
struct sockaddr_in *hostname_address;
const gchar *hostname = gtk_entry_get_text(GTK_ENTRY(widgets->textFieldHost));
int return_value;
gchar addr[INET_ADDRSTRLEN];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if((return_value = getaddrinfo(hostname,
gtk_entry_get_text(GTK_ENTRY(widgets->textFieldPort)),
&hints, &hostname_result)) != 0)
{
g_print("getaddrinfo: %s\n", gai_strerror(return_value));
return;
}
for(struct addrinfo *info_itr = hostname_result; info_itr != nullptr;
info_itr = info_itr->ai_next)
{
hostname_address = (struct sockaddr_in *)info_itr->ai_addr;
inet_ntop(AF_INET, &(hostname_address->sin_addr), addr, INET_ADDRSTRLEN);
g_print("%s:%s\n", addr, gtk_entry_get_text(GTK_ENTRY(widgets->textFieldPort)));
}
connect_to_logview(hostname_result);
freeaddrinfo(hostname_result);
}
void connect_to_logview(struct addrinfo *hostname_result)
{
int rv = 0;
sockfd = socket(hostname_result->ai_family, hostname_result->ai_socktype,
hostname_result->ai_protocol);
if(sockfd == -1)
{
perror("socket");
}
else
{
rv = connect(sockfd, hostname_result->ai_addr, hostname_result->ai_addrlen);
if(rv == -1)
{
perror("connect");
}
else
{
g_print("%s: Looks like we got something!\n", __FUNCTION__);
listen_for_logview();
}
}
}
void listen_for_logview()
{
fd_set fdset;
gchar buf[256];
int nbytes = 0;
bool exit = false;
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&fdset);
while(!exit)
{
if(select(sockfd+1, &fdset, NULL, NULL, &tv) == -1)
{
perror("select");
exit = true;
break;
}
if(FD_ISSET(sockfd, &fdset))
{
if((nbytes = recv(sockfd, buf, sizeof buf, 0)) <= 0)
{
perror("recv");
close(sockfd);
FD_CLR(sockfd, &fdset);
exit = true;
break;
}
else
{
g_print("!!!\n%s\n\n", buf);
close(sockfd);
FD_CLR(sockfd, &fdset);
exit = true;
break;
}
}
else
{
g_print("Timed out!\n");
tv.tv_sec = 2;
}
}
}
所以,這裏有什麼錯?我猜測答案是我只是濫用我所擁有的工具。除了上述兩種不當行爲之外,我還要感謝您在這裏看到的任何其他結構/技術問題。
在此先感謝您的幫助。
我把你的插座碼出你的UI代碼和一個整潔的小它自己的階級包起來,你可以分別測試。 – Galik
一旦我開始正確聽音,那肯定是我的方向。目前,只是爲了簡單起見,它們都在一個文件中。一旦我知道我必須做什麼來傾聽,我會從實際的對象/等開始。 – musasabi
GTK是一個古老的C庫,而不是C++。 Qt是一個C++版本。 –