代码: 全选
client.c
#include<gtk/gtk.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include "chatroom.h"
gint sd;
struct sockaddr_in s_in;
gchar username[NAME_SIZE];
gchar buf[BUF_SIZE];
// FIXME: why 1048?
//gchar get_buf[1048];
gchar get_buf[BUF_SIZE];
gboolean isconnected = FALSE;
static GtkWidget *text;
static GtkTextBuffer *buffer;
static GtkWidget *message_entry;
static GtkWidget *name_entry;
static GtkWidget *login_button;
void get_message(void) {
GtkTextIter iter;
gchar get_buf[BUF_SIZE];
gchar buf[BUF_SIZE];
while(read(sd, buf, BUF_SIZE) != -1) {
sprintf(get_buf, "%s", buf);
//gdk_threads_enter();
gtk_text_buffer_get_end_iter(buffer, &iter);
gtk_text_buffer_insert(buffer, &iter, get_buf, -1);
//gdk_threads_leave();
}
}
void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer data) {
sprintf(username, "guest");
if(do_connect() == TRUE) {
gtk_widget_set_sensitive(login_button, FALSE);
g_thread_new("get_message", (GThreadFunc)get_message, NULL);
}
gtk_widget_destroy(widget);
}
void on_button_clicked(GtkButton *button, gpointer data) {
const gchar *name;
name = gtk_entry_get_text(GTK_ENTRY(name_entry));
sprintf(username, "%s", name);
if(do_connect()) {
gtk_widget_set_sensitive(login_button, FALSE);
g_thread_new("get_message", (GThreadFunc)get_message, NULL);
}
gtk_widget_destroy(data);
}
void create_win(void) {
GtkWidget *win, *vbox;
GtkWidget *button;
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(win), "输入用户名");
gtk_container_set_border_width(GTK_CONTAINER(win), 10);
g_signal_connect(G_OBJECT(win), "delete_event",
G_CALLBACK(on_destroy), NULL);
gtk_window_set_modal(GTK_WINDOW(win), TRUE);
gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(win), vbox);
name_entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(vbox), name_entry, TRUE, TRUE, 5);
button = gtk_button_new_from_stock(GTK_STOCK_OK);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(on_button_clicked), win);
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 5);
gtk_widget_show_all(win);
}
gboolean do_connect(void) {
GtkTextIter iter;
gint slen;
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd < 0) {
gtk_text_buffer_get_end_iter(buffer, &iter);
gtk_text_buffer_insert(buffer, &iter, "打开套接字时出错!\n", -1);
return FALSE;
}
s_in.sin_family = AF_INET;
s_in.sin_port = OURPORT;
slen = sizeof(s_in);
if(connect(sd, &s_in, slen) < 0) {
gtk_text_buffer_get_end_iter(buffer, &iter);
gtk_text_buffer_insert(buffer, &iter, "连接服务器时出错!\n", -1);
return FALSE;
} else {
gtk_text_buffer_get_end_iter(buffer, &iter);
gtk_text_buffer_insert(buffer, &iter, username, -1);
gtk_text_buffer_get_end_iter(buffer, &iter);
gtk_text_buffer_insert(buffer, &iter, "\n成功与服务器连接..\n", -1);
write(sd, username, NAME_SIZE);
isconnected = TRUE;
return TRUE;
}
}
void on_send(GtkButton *button, gpointer data) {
const char *message;
if(isconnected == FALSE) {
return;
}
message = gtk_entry_get_text(GTK_ENTRY(message_entry));
sprintf(buf, "%s\n", message);
write(sd, buf, BUF_SIZE);
gtk_entry_set_text(GTK_ENTRY(message_entry), "");
}
void on_login(GtkWidget *button, gpointer data) {
create_win();
}
void on_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
close(sd);
gtk_main_quit();
}
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *vbox, *hbox, *button, *label, *view;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "客户端");
gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
gtk_container_set_border_width(GTK_CONTAINER(window), 5);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(on_delete_event), NULL);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
label = gtk_label_new("点击登陆按钮连接服务器");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
login_button = gtk_button_new_with_label("登录");
gtk_box_pack_start(GTK_BOX(hbox), login_button, FALSE, FALSE, 5);
g_signal_connect(G_OBJECT(login_button), "clicked",
G_CALLBACK(on_login), NULL);
view = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(view),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
text = gtk_text_view_new();
gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(view), text);
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
message_entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(hbox), message_entry, TRUE, TRUE, 0);
g_signal_connect(G_OBJECT(message_entry), "activate",
G_CALLBACK(on_send), NULL);
button = gtk_button_new_with_label("发送");
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(on_send), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
server.c
#include<glib.h>
#include<stdio.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/time.h>
#include<unistd.h>
#include<netdb.h>
#include<netinet/in.h>
#include "chatroom.h"
struct _client{
gint sd;
gboolean in_use;
gchar name[NAME_SIZE];
gchar buf[BUF_SIZE];
};
typedef struct _client client;
client users[MAX_USERS];
void do_service(gpointer id) {
gint j;
char tobuf[BUF_SIZE];
gint uid = GPOINTER_TO_INT(id);
while(read(users[uid].sd, users[uid].buf, BUF_SIZE) != -1) {
sprintf(tobuf, "%s:%s\n", users[uid].name, users[uid].buf);
for(j= 0; j < MAX_USERS; j++) {
if(users[j].in_use) {
write(users[j].sd,tobuf, BUF_SIZE);
g_print("%s", tobuf);
}
}
}
users[uid].in_use = FALSE;
close(users[uid].sd);
}
int main(int argc, char *argv[]) {
int sd, newsd;
struct sockaddr_in sin;
socklen_t slen;
gint count = 0;
gint flags;
gchar buf[BUF_SIZE];
gint i;
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd == -1) {
g_print("create socket error!\n");
return -1;
}
sin.sin_family = AF_INET;
sin.sin_port = OURPORT;
slen = sizeof(struct sockaddr_in);
if(bind(sd, &sin, slen) < 0) {
g_print("bind erro!\n");
return -1;
}
if(listen(sd, 8) < 0) {
g_print("listen error!\n");
return -1;
}
for(i = 0; i < MAX_USERS; i++) {
users[i].in_use = FALSE;
}
flags = fcntl(sd, F_GETFL);
fcntl(sd, F_SETFL, flags&~O_NDELAY);
while(TRUE) {
newsd = accept(sd, &sin, &slen);
if(newsd == -1) {
g_print("accept error!\n");
break;
} else {
if(count >= MAX_USERS) {
sprintf(buf, "用户数量过多服务器不能连接。\n");
write(newsd, buf, BUF_SIZE);
close(newsd);
} else {
flags = fcntl(users[i].sd, F_GETFL);
fcntl(users[i].sd, F_SETFL, O_NONBLOCK);
users[count].sd = newsd;
users[count].in_use = TRUE;
read(newsd, users[count].name, NAME_SIZE);
g_thread_new("do_server",
(GThreadFunc)do_service,
GINT_TO_POINTER(count));
count++;
}
}
}
printf("sd is never closed!\n");
close(sd);
return 0;
}
classroom.h
#ifndef _CHAT_ROOTM_H_
#define _CHAT_ROOTM_H_
#define OURPORT 8088
#define MAX_USERS 8
#define NAME_SIZE 64
#define BUF_SIZE 1024
#endif