首页 用gtk与winsock制作的局域网聊天工具[整理]

用gtk与winsock制作的局域网聊天工具[整理]

举报
开通vip

用gtk与winsock制作的局域网聊天工具[整理]用gtk与winsock制作的局域网聊天工具[整理] 用gtk与winsock制作的局域网聊天工具 //这是func.h的内容,包含了客户端所用到的头文件: #include #include #include #include #include #pragma comment(lib, "ws2_32.lib") extern const gchar *buf_chat; extern char buf_list[10000]; extern char buf_send[10000]; ex...

用gtk与winsock制作的局域网聊天工具[整理]
用gtk与winsock制作的局域网聊天工具[整理] 用gtk与winsock制作的局域网聊天工具 //这是func.h的内容,包含了客户端所用到的头文件: #include #include #include #include #include #pragma comment(lib, "ws2_32.lib") extern const gchar *buf_chat; extern char buf_list[10000]; extern char buf_send[10000]; extern char buf_recv[10000]; extern char MY_IP[100]; extern char chat[20]; extern char mytime[20]; extern char list[15]; extern char Tag[10]; extern SOCKADDR_IN address; extern gint flag; extern gint tag; extern time_t rawtime;//获取系统当前时间 extern struct tm * timeinfo; //-------------------------------------------------------- extern GtkWidget *window; extern GtkWidget *dialog; extern GtkWidget *window_start; extern GtkTextBuffer *buffer; //-------------------------------------------------------- gchar *str(char *);//将GB2312码转化为UTF-8码 gchar *srt(char *);//将UTF-8码转化为GB2312码 void store_add(GtkListStore *,char *);//给列 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 模型添加一行 void buffer_add(GtkTextBuffer *,char *);//给文本框添加一行 gint send_message(gpointer );//发送消息给服务器 void check(int *);//检测主机是否在线,用一个新的线程阻塞监听服务器 void check_chat(gpointer );//更新文本框聊天信息 gint check_list(gpointer );//更新上线主机列表 gint start(int *);//判断主机是否上线,若超时则提示 void my_quit();//退出程序并删除服务器主机列表上本机IP //这是func.c的内容,包括了客户端所用到的函数: #include "Func.h" gchar *str(char *string)//将GB2312码转化为UTF-8码 { return(g_locale_to_utf8(string,-1,NULL,NULL,NULL)); } gchar *srt(char *string)//将UTF-8码转化为GB2312码 { return(g_locale_from_utf8(string,-1,0,0,0)); } void store_add(GtkListStore *store,char *str)//给列表模型添加一行 { GtkTreeIter iter;//定义列表模型里列的行号 gtk_list_store_append(store,&iter);//在列表模型里添加一行 gtk_list_store_set(store,&iter,0,str,-1);//给新行设置属性 } void buffer_add(GtkTextBuffer *data,char *str)//给文本框添加一行 { GtkTextIter iter; gtk_text_buffer_get_end_iter(data,&iter);//使迭代标志指向文本缓冲的末尾 gtk_text_buffer_insert(data,&iter,str,-1);//往缓冲区的末尾添加文本 } gint send_message(gpointer data)//发送消息给服务器 { char *check_buf="\001";//--------------------------------------- -----------------------| SOCKET socket_client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //定 义socket句柄 connect(socket_client,(SOCKADDR*)&address,sizeof(address)); send(socket_client,check_buf,100,0);//-------------------------------------------------| buf_chat=srt(gtk_entry_get_text(GTK_ENTRY(data)));//获取 entry文本 strcpy(buf_send,"\005"); strcat(buf_send,MY_IP); strcat(buf_send,buf_chat); send(socket_client,buf_send,10000,0); closesocket(socket_client); gtk_entry_set_text(data,""); return TRUE; } void check(int *flag)//检测主机是否在线,并发送本机IP到主机 列表 { char *check_buf="\002";//--------------------------------------------------------------| SOCKET socket_client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(!connect(socket_client,(SOCKADDR*)&address,sizeof(address))) { send(socket_client,check_buf,100,0);//---------------------------------------------| send(socket_client,MY_IP,100,0);//像服务端发送本机IP closesocket(socket_client); *flag=0; } _endthread(); } void check_chat(gpointer data)//更新文本框聊天信息 { int i=0; int j=0; char *check_buf="\006";//--------------------------------------- -----------------------| SOCKET socket_client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //定义socket句柄 if(!connect(socket_client,(SOCKADDR*)&address,sizeof(add ress))) { send(socket_client,check_buf,100,0);//------------------ ---------------------------| sprintf(Tag,"%d",tag); send(socket_client,Tag,strlen(Tag),0);//发送本地文本框消息个数 //这里的"Tag"一定要作为strlen()来发送,否则会与服务器断开连接 recv(socket_client,Tag,100,0);//接收服务器消息个数 sscanf(Tag,"%d",&i);//把服务器消息个数同步到本地消息 个数 if(i!=tag) { tag=i; i=0; recv(socket_client,buf_recv,10000,0); //收到的消息有两条,要去掉收到的第一条消息(算法不成 功) char *p; char *q; p=buf_recv; q=buf_recv; while(*(p+j)) { if(p[j]=='\005') { q=p+j; i++; } if(i==2) break; j++; } strcpy(buf_recv,q);//获得服务器最后一条消息 i=0; p=buf_recv; q=buf_recv; while(buf_recv[i])//得到消息内的IP段 { if(i==1) q=p+i;//IP头 if(i==15) p=p+i;//消息头 i++; } strcpy(chat,q); chat[15]=0; time(&rawtime);//把时间加在IP后面 timeinfo=localtime(&rawtime); sprintf(mytime,"(%d:%d:%d)",timeinfo->tm_hour,timeinfo-> tm_min,timeinfo->tm_sec); strcat(chat,mytime); i=strlen(mytime); chat[15+i]='\n'; chat[16+i]=0; buffer_add(data,str(chat)); buffer_add(data,str(p)); buffer_add(data,"\n"); } strcpy(buf_recv,""); strcpy(chat,""); strcpy(mytime,""); closesocket(socket_client); } _endthread(); } gint check_list(gpointer data)//更新上线主机的列表 { _beginthread(check,0,&flag);//更新前发送本机IP _beginthread(check_chat,0,buffer); char *check_buf="\003";//--------------------------------------------------------------| SOCKET socket_client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(connect(socket_client,(SOCKADDR*)&address,sizeof(address))) { dialog=gtk_message_dialog_new(window,GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,str("连接服务器失败~")); gtk_window_set_title(GTK_WINDOW(dialog), str("发生错 误")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_hide_all(GTK_WINDOW(dialog)); gtk_list_store_clear(data); store_add(data,str("主机离线")); } else//若服务器在线则更新主机列表 { gtk_list_store_clear(data);//连接成功后清空本地主机列 表 send(socket_client,check_buf,100,0);//---------------------------------------------| recv(socket_client,buf_list,10000,0);//获取服务器在线 主机列表 int i=0; char *p; p=buf_list;//用外部指针去访问字符串里被隐藏的下标指针位置 while(*p) { while(i<=15) { list[i]=p[i]; i++; } list[i-1]=0; i=0; store_add(data,list); p=p+15; } strcpy(buf_list,""); strcpy(list,""); closesocket(socket_client); } return TRUE; } void my_quit()//退出程序并删除服务器主机列表上本机IP { char *check_buf="\004";//--------------------------------------- -----------------------| SOCKET socket_client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); connect(socket_client,(SOCKADDR*)&address,sizeof(address )); send(socket_client,check_buf,100,0);//------------------ -------------------------------| send(socket_client,MY_IP,100,0); closesocket(socket_client); gtk_main_quit(); } gint start(int *flag)//判断主机是否上线,若超时则提示 { if(*flag==0) { gtk_widget_destroy(window_start); gtk_widget_show_all(window); return FALSE; } (*flag)++; if((*flag)>=30)//如果连接超时出现警告窗口 { gtk_window_set_keep_above(GTK_WINDOW(window_start),FALSE ); dialog=gtk_message_dialog_new(window_start,GTK_DIALOG_MODAL ,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,str("连接服务器失败~")); gtk_window_set_title(GTK_WINDOW(dialog),str("发生错误")); gtk_dialog_run(GTK_DIALOG(dialog)); //gtk_widget_destroy(dialog);//销毁警告窗口,继续程序 gtk_widget_hide_all(GTK_WINDOW(dialog));//隐藏警告窗 口,继续程序 gtk_widget_destroy(GTK_WINDOW(window_start)); gtk_widget_show_all(GTK_WINDOW(window)); return FALSE; } return TRUE; } //这是客户端的主函数和全局变量的定义,主函数中包含大量的gtk+ 的构建: #include "Func.h" const gchar *buf_chat; char buf_list[10000]; char buf_send[10000]; char buf_recv[10000]; char MY_IP[100]; char chat[20]; char mytime[20]; char list[15]; char Tag[10]; SOCKADDR_IN address; GtkWidget *window; GtkWidget *dialog; GtkWidget *window_start; GtkTextBuffer *buffer; gint flag=1; gint tag=0; time_t rawtime;//获取系统当前时间 struct tm * timeinfo; int main(int argc, char *argv[]) { //定义 ----------------------------------------------------------- -------------------------------------------- GtkWidget *button;//声明构件指针 GtkWidget *entry; GtkWidget *table; GtkWidget *frame; GtkWidget *progressBar; GtkWidget *view_chat; GtkWidget *view_list;//定义列表 GtkListStore *view_list_store;//定义列表模型 GtkCellRenderer *view_list_renderer_text;//定义列表渲染器为文本渲染 GtkTreeViewColumn *view_list_column;//定义列表行 GtkWidget *scrolled_chat; GtkWidget *scrolled_list; //环境 ----------------------------------------------------------- -------------------------------------------- WSADATA WASdata;//初始化winsock环境 WSAStartup(MAKEWORD(2,2),&WASdata); address.sin_family=AF_INET; address.sin_port=htons(60000); address.sin_addr.s_addr=inet_addr("172.16.104.123"); gtk_init(&argc,&argv); //声明 ------------------------------------------------------------------------------------------------------- entry=gtk_entry_new();//定义构件指针 button=gtk_button_new_with_label(str("确定")); window=gtk_window_new(GTK_WINDOW_TOPLEVEL); window_start=gtk_window_new(GTK_WINDOW_TOPLEVEL); progressBar=gtk_progress_bar_new(); table=gtk_table_new(10,18,TRUE); view_chat=gtk_text_view_new();//显示聊天信息的文本框 buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(view_chat) );//获得文本框的缓冲区 view_list_renderer_text=gtk_cell_renderer_text_new(); view_list_column=gtk_tree_view_column_new(); view_list_store=gtk_list_store_new(1,G_TYPE_STRING);//创 建列表模型为1列,字符串型 view_list=gtk_tree_view_new_with_model(GTK_TREE_MODEL(view_list_store));//把列表模型加入列表并创建 scrolled_chat=gtk_scrolled_window_new(NULL,NULL); scrolled_list=gtk_scrolled_window_new(NULL,NULL); //属性 ------------------------------------------------------------------------------------------------------- gtk_widget_set_size_request(GTK_WINDOW(window_start),180 ,20);//设置窗口最小大小 gtk_window_set_resizable(GTK_WINDOW(window_start),FALSE);//使窗口大小不可改变 gtk_window_set_decorated(GTK_WINDOW(window_start),FALSE);//去掉边框 gtk_window_set_position(GTK_WINDOW(window_start),GTK_WIN_POS_CENTER); gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window),320,240);//窗口默认大小,会被改变 gtk_container_border_width(GTK_CONTAINER(window),5); gtk_window_set_title(GTK_WINDOW(window),"Client"); gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progressBar));//设置进度条显示方式 gtk_table_set_row_spacings(GTK_TABLE(table),5);//table行 列间隔 gtk_table_set_col_spacings(GTK_TABLE(table),5); gtk_scrolled_window_set_policy(scrolled_chat,GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);//滚动窗口滚动条出现策略 gtk_scrolled_window_set_policy(scrolled_list,GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); gtk_text_view_set_editable(view_chat,FALSE);//设置文本框 不可编辑 gtk_text_view_set_wrap_mode(view_chat,GTK_WRAP_CHAR);// 设置文本框水平超出界面就换行 gtk_tree_view_column_pack_start(view_list_column,view_list_renderer_text,FALSE);//把列表渲染器关联列表列 gtk_tree_view_append_column(GTK_TREE_VIEW(view_list),view_list_column);//把列表列关联列表模型 gtk_tree_view_column_add_attribute(view_list_column,view_list_renderer_text,"text",NULL);//为列表渲染器添加属性 gtk_tree_view_column_set_title(view_list_column,str("在 线主机")); //组装 ------------------------------------------------------------------------------------------------------- gtk_container_add(GTK_CONTAINER(window_start),progressBar);//将构件装进盒子 gtk_container_add(GTK_CONTAINER(scrolled_chat),view_chat);//为文本框添加滚动条 gtk_container_add(GTK_CONTAINER(scrolled_list),view_list); gtk_table_attach(GTK_TABLE(table),scrolled_chat,0,12,0,8,GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,0); gtk_table_attach(GTK_TABLE(table),scrolled_list,12,18,0,8,GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,0); gtk_table_attach(GTK_TABLE(table),entry,0,12,8,10,GTK_EXPAND|GTK_FILL,GTK_EXPAND,0,0); gtk_table_attach(GTK_TABLE(table),button,12,18,8,10,GTK_ EXPAND|GTK_FILL,GTK_EXPAND,0,0); gtk_container_add(GTK_CONTAINER(window),table); //信号 ------------------------------------------------------------------------------------------------------- g_signal_connect_swapped(G_OBJECT(button),"clicked",G_CALLBACK(send_message),entry); g_signal_connect(G_OBJECT(entry),"activate",G_CALLBACK(send_message),entry); g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(my_quit),NULL); //初始化 ------------------------------------------------------------------------------------------------------- //本机IP初始化 ------------------------------------------- int i=0; struct hostent *Host; struct in_addr addr; gethostname(MY_IP,100);//获取本机主机名 Host=gethostbyname(MY_IP);//用主机名获取主机IP addr.s_addr=*(u_long*)Host->h_addr_list[0];//格式转换 strcpy(MY_IP,inet_ntoa(addr)); while(MY_IP[i]) i++; while(i<=15) { if(i<=14) MY_IP[i]=32; else MY_IP[i]=0; i++; } //------------------------------------------------------ - gtk_widget_show_all(window_start); gtk_window_set_keep_above(GTK_WINDOW(window_start),TRUE) ;//使进度条窗口显示在所有窗口上面 gtk_timeout_add(500,G_CALLBACK(start),&flag);//重复检测主机状态,直到确认在线。 gtk_timeout_add(3500,G_CALLBACK(check_list),view_list_st ore);//重复检测在线主机列表 gtk_main();//执行GTK return 0; } //这是服务器的那端 #include #include #include #pragma comment(lib, "ws2_32.lib") char buf[10000]; char buf_list[10000]; char buf_chat[10000]; char *check_make_list="\002"; char *check_read_list="\003"; char *check_dele_list="\004"; char *check_make_chat="\001"; char *check_read_chat="\006"; char number[10]; char list[15]; int tag=0; int compstr(char *p,char *q) { int n=0,m=0,k=0; while(*(p+n)) n++; while(*(q+m)) m++; if(n==m) { while(*(p++)==*(q++)) k++; if((k-1)>=m) return 1; else return 0; } else return 0; } void myaccept(SOCKET socket_link) { recv(socket_link,buf,100,0); if(compstr(buf,check_make_chat))//接收主机消息 { recv(socket_link,buf,10000,0); strcat(buf_chat,buf); tag++;//服务器消息队列加1 } if(compstr(buf,check_read_chat))//发送主机聊天信息(算法不成功) { int num=0; recv(socket_link,buf,100,0);//接收主机消息个数与服务器对比 sscanf(buf,"%d",&num);//把主机消息个数转为数字作标记 sprintf(number,"%d",tag);//把消息个数赋值到字符串与主 机消息个数比较 send(socket_link,number,strlen(number),0);//使主机消 息个数与服务器同步 if(!compstr(buf,number)) { int i=0; int j=0; char *p; char *q; p=buf_chat; q=buf_chat; while(*(p+j)) { if(p[j]=='\005') { q=p+j; i++; } if(i==num) break; j++; } send(socket_link,q,strlen(q),0);//这里q用strlen() 来发送 //所发送的消息只是服务器的最后两条(算法不成功) } strcpy(number,""); } if(compstr(buf,check_make_list))//添加在线列表 { recv(socket_link,buf,100,0); char *p; int i=0; int k=0; p=buf_list; while(*p)//检查在线主机是否重复 { while(i<=15) { list[i]=p[i]; i++; } list[i-1]=0; i=0; if(compstr(buf,list)) k=1; p=p+15; } if(k==0) strcat(buf_list,buf); } if(compstr(buf,check_read_list))//发送在线列表 { send(socket_link,buf_list,10000,0); } if(compstr(buf,check_dele_list))//把离线的主机从列表中删除 { recv(socket_link,buf,100,0); char *p; char *q; int i=0; p=buf_list; while(*p)//标记主机所在下标位置 { while(i<=15) { list[i]=p[i]; i++; } list[i-1]=0; i=0; if(compstr(buf,list)) { q=p; p=p+15; break; } p=p+15; } strcpy(q,p);//把主机从列表中删除 strcpy(buf_list,q); } closesocket(socket_link); _endthread(); } int main() { WSADATA WASdata;//定义存储初始化信息的全局结构体 WSAStartup(MAKEWORD(2,2),&WASdata);//初始化winsock环境 SOCKET socket_server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//定义socket句柄 SOCKET socket_link; SOCKADDR_IN address;//定义地址结构体 address.sin_family=AF_INET; //定义Internet地址簇 address.sin_port=htons(60000); //定义端口 address.sin_addr.s_addr=inet_addr("0.0.0.0"); //定义地址 bind(socket_server,(SOCKADDR*)&address,sizeof(address)); //将socket与端口、地址绑定 listen(socket_server,10);//使socket进入监听队列 while(1) { socket_link=accept(socket_server,NULL,NULL);//对socket指定的地址进行监听 _beginthread(myaccept,0,socket_link); } closesocket(socket_server); WSACleanup(); return 0; } //本来是想做linux与windows通用的程序的,但是socket编程以winsock比较容易,所以就先拿winsock来练手了.
本文档为【用gtk与winsock制作的局域网聊天工具[整理]】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_153723
暂无简介~
格式:doc
大小:54KB
软件:Word
页数:0
分类:
上传时间:2018-09-20
浏览量:11