c语言的聊天界面化
linux安装c的gtk图形库
然后代码如下,编译运行即可,需要两台机器都是用以下代码,编译后双击即可,
然后这两台机器即可通信
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#define PORT 8888
#define MAXSIZE 1024
int sockfd;
int issucceed=-1;
GtkTextBuffer *show_buffer,*input_buffer;
void get_ip(GtkWidget *,gpointer);
void quit_win(GtkWidget *,gpointer);
struct sockaddr_in saddr;
struct sockaddr_in caddr;
void show_err(char *err)
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(show_buffer),&start,&end);
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,err,strlen(err));
}
void show_remote_text(char rcvd_mess[])
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(show_buffer),&start,&end);
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"他说:\n",8);
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,rcvd_mess,strlen(rcvd_mess)-1);
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"\n",1);
}
void quit_win(GtkWidget *window,gpointer data)
{
gtk_main_quit();
}
void *recv_func(void *arg)
{
char rcvd_mess[MAXSIZE];
socklen_t len=sizeof(caddr);
while(1)
{
bzero(rcvd_mess,MAXSIZE);
if(recv(sockfd,rcvd_mess,sizeof(rcvd_mess),0)==-1) /*阻塞直到收到客户端发的消息*/
continue;
show_remote_text(rcvd_mess);
}
}
void show_local_text(const gchar* text)
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(show_buffer),&start,&end);/*获得缓冲区开始和结束位置的Iter*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"我说:\n",8);/*插入文本到缓冲区*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,text,strlen(text));/*插入文本到缓冲区*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"\n",1);/*插入文本到缓冲区*/
}
void clean_send_text()
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(input_buffer),&start,&end);
gtk_text_buffer_delete(GTK_TEXT_BUFFER(input_buffer),&start,&end);
}
void send_func(const char *text)
{
int n;
socklen_t len=sizeof(saddr);
n=sendto(sockfd,text,MAXSIZE,0,(const struct sockaddr*)&saddr,len);
if(n<0)
{
perror("Send error!");
exit(1);
}
}
int build_socket(const char *serv_ip)
{
int res;
pthread_t recv_thread;
pthread_attr_t thread_attr;
res=pthread_attr_init(&thread_attr);
if(res!=0)
{
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)
{
perror("Socket Error");
exit(1);
}
bzero(&saddr,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(PORT);
saddr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sockfd,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in))==-1)
{
perror("Bind Error");
exit(1);
}
res=inet_pton(AF_INET,serv_ip,&saddr.sin_addr);
if(res==0){
return 1;
}
else if(res==-1){
return -1;
}
res=pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED);
if(res!=0)
{
perror("Failed to set the separate state of threads!");
exit(EXIT_FAILURE);
}
res=pthread_create(&recv_thread,&thread_attr,recv_func,NULL);
if(res!=0)
{
perror("Thread create error!");
exit(EXIT_FAILURE);
}
(void)pthread_attr_destroy(&thread_attr);
return 0;
}
void send_text()
{
GtkTextIter start,end;
gchar *text;
if(issucceed==-1){
show_err("未建立链接...\n");
}
else
{
text=(gchar *)malloc(MAXSIZE);
if(text==NULL)
{
printf("Malloc error!\n");
sleep(3);
exit(1);
}
/* get text */
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(input_buffer),&start,&end);
text=gtk_text_buffer_get_text(GTK_TEXT_BUFFER(input_buffer),&start,&end,FALSE);
if(strcmp(text,"")!=0)
{
send_func(text);
clean_send_text();
show_local_text(text);
}
else
show_err("Messages cannot be empty!!!\n");
}
}
void get_ip(GtkWidget *button,gpointer ip_text)
{
gchar *his_ip;
int res;
his_ip=(gchar *)gtk_entry_get_text(GTK_ENTRY((GtkWidget *)ip_text));
res=build_socket(his_ip);
if(res==1)
show_err("Invalid IPaddress!\n");
else if(res==-1)
show_err("Feild link! \n");/*插入文本到缓冲区*/
else{
show_err("Succeed link! \n");
issucceed=0;
}
}
int main(int argc,char **argv)
{
GtkWidget *window;
GtkWidget *show_text,*input_text,*ip_text;
GtkWidget *ip_label,*space_label,*histroy_label,*input_label;
GtkWidget *link_button,*send_button,*quit_button;
GtkWidget *hbox,*vbox;
GtkWidget *scrolled1,*scrolled2;
gtk_init(&argc,&argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"Intimate Relationship");
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window),430,320);
g_signal_connect(GTK_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);
ip_label=gtk_label_new("IP:");
histroy_label=gtk_label_new("histroy");
input_label=gtk_label_new("messages");
space_label=gtk_label_new(" ");
link_button=gtk_button_new_with_label("连接");
send_button=gtk_button_new_with_label("发送");
quit_button=gtk_button_new_with_label("关闭");
ip_text=gtk_entry_new();
show_text=gtk_text_view_new();
input_text=gtk_text_view_new();
/* set length of IP box */
gtk_entry_set_max_length(GTK_ENTRY(ip_text),15);
/* get the buffer of textbox */
show_buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(show_text));
input_buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(input_text));
/* set textbox to diseditable */
gtk_text_view_set_editable(GTK_TEXT_VIEW(show_text),FALSE);
scrolled1=gtk_scrolled_window_new(NULL,NULL);
scrolled2=gtk_scrolled_window_new(NULL,NULL);
gtk_widget_set_size_request(scrolled1,50,80);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled1),show_text);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled2),input_text);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled1),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled2),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
hbox=gtk_hbox_new(FALSE,2);
vbox=gtk_vbox_new(FALSE,2);
g_signal_connect(GTK_OBJECT(quit_button),"clicked",G_CALLBACK(gtk_main_quit),NULL);
g_signal_connect(GTK_OBJECT(link_button),"clicked",GTK_SIGNAL_FUNC(get_ip),ip_text);
gtk_box_pack_start(GTK_BOX(hbox),ip_label,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),ip_text,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),link_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),space_label,TRUE,TRUE,2);
gtk_box_pack_start(GTK_BOX(hbox),send_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),quit_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(vbox),histroy_label,FALSE,TRUE,2);
gtk_box_pack_start(GTK_BOX(vbox),scrolled1,TRUE,TRUE,2);
gtk_box_pack_start(GTK_BOX(vbox),input_label,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(vbox),scrolled2,TRUE,TRUE,2);
gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,2);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_signal_connect(GTK_OBJECT(send_button),"clicked",GTK_SIGNAL_FUNC(send_text),NULL);
gtk_widget_show_all(window);
gtk_main();
return FALSE;
}
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#define PORT 8888
#define MAXSIZE 1024
int sockfd;
int issucceed=-1;
GtkTextBuffer *show_buffer,*input_buffer;
void get_ip(GtkWidget *,gpointer);
void quit_win(GtkWidget *,gpointer);
struct sockaddr_in saddr;
struct sockaddr_in caddr;
void show_err(char *err)
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(show_buffer),&start,&end);
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,err,strlen(err));
}
void show_remote_text(char rcvd_mess[])
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(show_buffer),&start,&end);
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"他说:\n",8);
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,rcvd_mess,strlen(rcvd_mess)-1);
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"\n",1);
}
void quit_win(GtkWidget *window,gpointer data)
{
gtk_main_quit();
}
void *recv_func(void *arg)
{
char rcvd_mess[MAXSIZE];
socklen_t len=sizeof(caddr);
while(1)
{
bzero(rcvd_mess,MAXSIZE);
if(recv(sockfd,rcvd_mess,sizeof(rcvd_mess),0)==-1) /*阻塞直到收到客户端发的消息*/
continue;
show_remote_text(rcvd_mess);
}
}
void show_local_text(const gchar* text)
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(show_buffer),&start,&end);/*获得缓冲区开始和结束位置的Iter*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"我说:\n",8);/*插入文本到缓冲区*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,text,strlen(text));/*插入文本到缓冲区*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"\n",1);/*插入文本到缓冲区*/
}
void clean_send_text()
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(input_buffer),&start,&end);
gtk_text_buffer_delete(GTK_TEXT_BUFFER(input_buffer),&start,&end);
}
void send_func(const char *text)
{
int n;
socklen_t len=sizeof(saddr);
n=sendto(sockfd,text,MAXSIZE,0,(const struct sockaddr*)&saddr,len);
if(n<0)
{
perror("Send error!");
exit(1);
}
}
int build_socket(const char *serv_ip)
{
int res;
pthread_t recv_thread;
pthread_attr_t thread_attr;
res=pthread_attr_init(&thread_attr);
if(res!=0)
{
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)
{
perror("Socket Error");
exit(1);
}
bzero(&saddr,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(PORT);
saddr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sockfd,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in))==-1)
{
perror("Bind Error");
exit(1);
}
res=inet_pton(AF_INET,serv_ip,&saddr.sin_addr);
if(res==0){
return 1;
}
else if(res==-1){
return -1;
}
res=pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED);
if(res!=0)
{
perror("Failed to set the separate state of threads!");
exit(EXIT_FAILURE);
}
res=pthread_create(&recv_thread,&thread_attr,recv_func,NULL);
if(res!=0)
{
perror("Thread create error!");
exit(EXIT_FAILURE);
}
(void)pthread_attr_destroy(&thread_attr);
return 0;
}
void send_text()
{
GtkTextIter start,end;
gchar *text;
if(issucceed==-1){
show_err("未建立链接...\n");
}
else
{
text=(gchar *)malloc(MAXSIZE);
if(text==NULL)
{
printf("Malloc error!\n");
sleep(3);
exit(1);
}
/* get text */
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(input_buffer),&start,&end);
text=gtk_text_buffer_get_text(GTK_TEXT_BUFFER(input_buffer),&start,&end,FALSE);
if(strcmp(text,"")!=0)
{
send_func(text);
clean_send_text();
show_local_text(text);
}
else
show_err("Messages cannot be empty!!!\n");
}
}
void get_ip(GtkWidget *button,gpointer ip_text)
{
gchar *his_ip;
int res;
his_ip=(gchar *)gtk_entry_get_text(GTK_ENTRY((GtkWidget *)ip_text));
res=build_socket(his_ip);
if(res==1)
show_err("Invalid IPaddress!\n");
else if(res==-1)
show_err("Feild link! \n");/*插入文本到缓冲区*/
else{
show_err("Succeed link! \n");
issucceed=0;
}
}
int main(int argc,char **argv)
{
GtkWidget *window;
GtkWidget *show_text,*input_text,*ip_text;
GtkWidget *ip_label,*space_label,*histroy_label,*input_label;
GtkWidget *link_button,*send_button,*quit_button;
GtkWidget *hbox,*vbox;
GtkWidget *scrolled1,*scrolled2;
gtk_init(&argc,&argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"Intimate Relationship");
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window),430,320);
g_signal_connect(GTK_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);
ip_label=gtk_label_new("IP:");
histroy_label=gtk_label_new("histroy");
input_label=gtk_label_new("messages");
space_label=gtk_label_new(" ");
link_button=gtk_button_new_with_label("连接");
send_button=gtk_button_new_with_label("发送");
quit_button=gtk_button_new_with_label("关闭");
ip_text=gtk_entry_new();
show_text=gtk_text_view_new();
input_text=gtk_text_view_new();
/* set length of IP box */
gtk_entry_set_max_length(GTK_ENTRY(ip_text),15);
/* get the buffer of textbox */
show_buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(show_text));
input_buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(input_text));
/* set textbox to diseditable */
gtk_text_view_set_editable(GTK_TEXT_VIEW(show_text),FALSE);
scrolled1=gtk_scrolled_window_new(NULL,NULL);
scrolled2=gtk_scrolled_window_new(NULL,NULL);
gtk_widget_set_size_request(scrolled1,50,80);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled1),show_text);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled2),input_text);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled1),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled2),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
hbox=gtk_hbox_new(FALSE,2);
vbox=gtk_vbox_new(FALSE,2);
g_signal_connect(GTK_OBJECT(quit_button),"clicked",G_CALLBACK(gtk_main_quit),NULL);
g_signal_connect(GTK_OBJECT(link_button),"clicked",GTK_SIGNAL_FUNC(get_ip),ip_text);
gtk_box_pack_start(GTK_BOX(hbox),ip_label,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),ip_text,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),link_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),space_label,TRUE,TRUE,2);
gtk_box_pack_start(GTK_BOX(hbox),send_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),quit_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(vbox),histroy_label,FALSE,TRUE,2);
gtk_box_pack_start(GTK_BOX(vbox),scrolled1,TRUE,TRUE,2);
gtk_box_pack_start(GTK_BOX(vbox),input_label,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(vbox),scrolled2,TRUE,TRUE,2);
gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,2);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_signal_connect(GTK_OBJECT(send_button),"clicked",GTK_SIGNAL_FUNC(send_text),NULL);
gtk_widget_show_all(window);
gtk_main();
return FALSE;
}