您的位置:首页 > 理论基础 > 计算机网络

Linux Socket 网络编程 基于GTK+ 的多线程实现的局域网通信软件

2010-12-27 15:16 1121 查看
本程序的通信是基于UDP协议的传输实现

服务器端:

server.h

/***********************************
* server.h                        *
* the header files and functions  *
***********************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#define bool _Bool
#define true 1
#define false 0
#define PORT 8888
#define MAXSIZE 1024
void *recv_func(void *arg);
int build_socket();
void send_text(void);
void send_func(const char *);
void show_remote_text(char rcvd_mess[]);
void show_err(char *err);
void clean_send_text(void);
void startup(void);


se_sock.c

/************************************************
* se_sock.c                                  		     *
* function:                                  		     *
*    create a socket                        		     *
*    create a new thread,for receive function  *
*    send message                             	      *
************************************************/
#include "server.h"
socklen_t len;
bool from_host;//表示客户端是否已经向本服务器发送来信息
int sockfd;
struct sockaddr_in saddr,caddr;//saddr表示本地服务器地址信息,caddr用于保存向本服务器发送信息的主机地址信息
int build_socket()
{
int res;
pthread_t recv_thread;
pthread_attr_t thread_attr;
len=sizeof(caddr);
/* Set status of thread */
res=pthread_attr_init(&thread_attr);
if(res!=0)
{
show_err("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
/* Create a socket */
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)
{
show_err("Socket Error");
exit(1);
}

bzero(&saddr,sizeof(struct sockaddr));
saddr.sin_family=AF_INET;
saddr.sin_addr.s_addr=htonl(INADDR_ANY);
saddr.sin_port=htons(PORT);
if(bind(sockfd,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in))==-1)
{
show_err("Bind Error");
exit(1);
}
/* Set the status of thread,don't wait for return of the subthread */
res=pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED);
if(res!=0)
{
show_err("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
/* Create a sub thread,call recv_func() */
res=pthread_create(&recv_thread,&thread_attr,recv_func,NULL);
if(res!=0)
{
show_err("Thread create error");
exit(EXIT_FAILURE);
}
/* Callback the attribute of thread */
(void)pthread_attr_destroy(&thread_attr);
}
/* Receive function */
void *recv_func(void *arg)
{
char recv_text[MAXSIZE];
while(1)
{	/* To Receive message from client and get the address infomation */
if(recvfrom(sockfd,recv_text,sizeof(recv_text),0,(struct sockaddr*)&caddr,&len)<0)
{
show_err("server recv error");
exit(1);
}
if( from_host==false ) from_host=true;
show_remote_text(recv_text);
}
}
/* Send function,send message to client */
void send_func(const char * send_text)
{
/* If there is no text,continue */
if(strlen(send_text)==1)
return;
if( !from_host ) show_err("Unknown the client's address infomation/nPlease wait the client to connect you first !/n");
/* Send message */
if(from_host && sendto(sockfd,send_text,MAXSIZE,0,(struct sockaddr*)&caddr,len)<0)
{
show_err("S send error");
exit(1);
}
}


server.c

/*************************************************
* server.c                                    		  *
*   create the server window    		  *
*   send message to client          		  *
*************************************************/
#include "server.h"
#include<gtk/gtk.h>
bool socket_start;
GtkTextBuffer *show_buffer,*input_buffer;
void quit_win(GtkWidget *,gpointer);
int main(int argc,char **argv)
{
GtkWidget *window;
GtkWidget *show_text,*input_text;
GtkWidget *send_button,*quit_button,*cls_button,*start_button;
GtkWidget *hbox,*vbox;
GtkWidget *scrolled1,*scrolled2;
GtkWidget *space_label;
gtk_init(&argc,&argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"Server");
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window),430,320);
/* "quit" button */
g_signal_connect(GTK_OBJECT(window),"destroy",GTK_SIGNAL_FUNC(quit_win),NULL);

space_label=gtk_label_new("                          ");
/* set button */
send_button=gtk_button_new_with_label("Send");
quit_button=gtk_button_new_with_label("Close");
cls_button=gtk_button_new_with_label("Clear");
start_button=gtk_button_new_with_label("Startup");
/* set textbox */
show_text=gtk_text_view_new();
input_text=gtk_text_view_new();
/* 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);
/* scroll window */
scrolled1=gtk_scrolled_window_new(NULL,NULL);
scrolled2=gtk_scrolled_window_new(NULL,NULL);
/* create a textbox */
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled1),show_text);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled2),input_text);
/* setting of window */
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);
/* click quit to call quit_win*/
g_signal_connect(GTK_OBJECT(quit_button),"clicked",GTK_SIGNAL_FUNC(quit_win),NULL);
/* click to clear input screen*/
g_signal_connect(GTK_OBJECT(cls_button),"clicked",GTK_SIGNAL_FUNC(clean_send_text),NULL);
/* click Start to build socket*/
g_signal_connect(GTK_OBJECT(start_button),"clicked",GTK_SIGNAL_FUNC(startup),NULL);
/* create window */
gtk_box_pack_start(GTK_BOX(hbox),start_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),cls_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),quit_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(vbox),scrolled1,TRUE,TRUE,2);
gtk_box_pack_start(GTK_BOX(vbox),scrolled2,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,2);
gtk_container_add(GTK_CONTAINER(window),vbox);
/* click send button ,then call send_text*/
gtk_signal_connect(GTK_OBJECT(send_button),"clicked",GTK_SIGNAL_FUNC(send_text),NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
/* show the input text */
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,"Me:/n",4);/*插入文本到缓冲区*/
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);/*插入文本到缓冲区*/
}
/* clean the input text */
void clean_send_text()
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(input_buffer),&start,&end);/*获得缓冲区开始和结束位置的Iter*/
gtk_text_buffer_delete(GTK_TEXT_BUFFER(input_buffer),&start,&end);/*插入到缓冲区*/
}
/* get the input text,and send it */
void send_text()
{
GtkTextIter start,end;
gchar *text;
/* Socket creating has succeed ,so send message */
text=(gchar *)malloc(MAXSIZE);
if(text==NULL)
{
printf("Malloc error!/n");
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 there is no input,do nothing but return */
if(strcmp(text,"")!=0)
{
send_func(text);
clean_send_text();
show_local_text(text);
}
else
show_err("The message can not be empty .../n");
free(text);
}
void startup(void)
{
if( !socket_start )
{
build_socket();
socket_start=true;
return;
}
show_err("The server has been started !/n");
}
/* show errors such as "no input","haven't create sockt" etc. */
void show_err(char *err)
{
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,err,strlen(err));
}

/* show the received message */
void show_remote_text(char rcvd_mess[])
{
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,"Client:/n",8);/*插入文本到缓冲区*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,rcvd_mess,strlen(rcvd_mess));/*插入文本到缓冲区*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"/n",1);/*插入换行到缓冲区*/
}
/* quit */
void quit_win(GtkWidget *window,gpointer data)
{
gtk_main_quit();
}


客户端

client.h

/***********************************
* client.h                        *
* the header files and functions  *
***********************************/
#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 build_socket(const char *);
void send_text(void);
void send_func(const char *);
void *recv_func(void *);
void show_remote_text(char rcvd_mess[]);
void clean_send_text(void);
void show_err(char *err);


cl_sock.c

/************************************************
* cl_sock.c                                    			*
* function:                                   			 *
*    create a socket                           		 *
*    create a new thread,for receive function     *
*    send message                             		 *
************************************************/
#include "client.h"
int sockfd;
struct sockaddr_in saddr;
int build_socket(const char *serv_ip)
{
int res;
pthread_t recv_thread;
pthread_attr_t thread_attr;
/* set status of thread */
res=pthread_attr_init(&thread_attr);
if(res!=0)
{
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
sockfd=socket(AF_INET,SOCK_DGRAM,0); /* create a socket */
if(sockfd==-1)
{
perror("Socket Error");
exit(1);
}
bzero(&saddr,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(PORT);
res=inet_pton(AF_INET,serv_ip,&saddr.sin_addr);
if(res==0){ /* the serv_ip is invalid */
return 1;
}
else if(res==-1){
return -1;
}
/* set the stats of thread:means do not wait for the return value of subthread */
res=pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED);
if(res!=0)
{
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
/* Create a thread,to process the receive function. */
res=pthread_create(&recv_thread,&thread_attr,&recv_func,NULL);
if(res!=0)
{
perror("Thread create error");
exit(EXIT_FAILURE);
}
/* callback the attribute */
(void)pthread_attr_destroy(&thread_attr);
return 0;
}
/* send function */
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("S send error");
exit(1);
}
}
/* a new thread,to receive message */
void *recv_func(void *arg)
{
char rcvd_mess[MAXSIZE];
while(1)
{
bzero(rcvd_mess,MAXSIZE);
if(recvfrom(sockfd,rcvd_mess,MAXSIZE,0,NULL,NULL)<0)  /*阻塞直到收到客户端发的消息*/
{
perror("server recv error");
exit(1);
}
show_remote_text(rcvd_mess);
}
}


client.c

/*********************************
* Client.c                     		 *
* Function:                    		 *
*    create the chat window      *
*********************************/
#include "client.h"
#include <gtk/gtk.h>
int issucceed=-1;
GtkTextBuffer *show_buffer,*input_buffer;
void get_ip(GtkWidget *,gpointer);
void quit_win(GtkWidget *,gpointer);
int main(int argc,char **argv)
{
GtkWidget *window;
GtkWidget *show_text,*input_text,*ip_text;
GtkWidget *ip_label,*space_label;
GtkWidget *link_button,*send_button,*quit_button,*cls_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),"Client");
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window),430,320);
/* "quit" button */
g_signal_connect(GTK_OBJECT(window),"destroy",GTK_SIGNAL_FUNC(quit_win),NULL);
ip_label=gtk_label_new("IP:");
space_label=gtk_label_new("                          ");
/* set button */
link_button=gtk_button_new_with_label("Connect");
send_button=gtk_button_new_with_label("Send");
quit_button=gtk_button_new_with_label("Close");
cls_button=gtk_button_new_with_label("Clear");

/* set textbox */
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);
/* scroll window */
scrolled1=gtk_scrolled_window_new(NULL,NULL);
scrolled2=gtk_scrolled_window_new(NULL,NULL);
/* create a textbox */
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled1),show_text);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled2),input_text);
/* setting of window */
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);
/* click quit to call quit_win*/
g_signal_connect(GTK_OBJECT(quit_button),"clicked",GTK_SIGNAL_FUNC(quit_win),NULL);
/* click "connect" to call get_ip */
g_signal_connect(GTK_OBJECT(link_button),"clicked",GTK_SIGNAL_FUNC(get_ip),ip_text);
/* click to clear input screen*/
g_signal_connect(GTK_OBJECT(cls_button),"clicked",GTK_SIGNAL_FUNC(clean_send_text),NULL);
/* create window */
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),cls_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(hbox),quit_button,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(vbox),scrolled1,TRUE,TRUE,2);
gtk_box_pack_start(GTK_BOX(vbox),scrolled2,FALSE,FALSE,2);
gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,2);
gtk_container_add(GTK_CONTAINER(window),vbox);
/* click send button ,then call send_text*/
gtk_signal_connect(GTK_OBJECT(send_button),"clicked",GTK_SIGNAL_FUNC(send_text),NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
/* show the input text */
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,"Me:/n",4);/*插入文本到缓冲区*/
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);/*插入文本到缓冲区*/
}
/* clean the input text */
void clean_send_text()
{
GtkTextIter start,end;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(input_buffer),&start,&end);/*获得缓冲区开始和结束位置的Iter*/
gtk_text_buffer_delete(GTK_TEXT_BUFFER(input_buffer),&start,&end);/*插入到缓冲区*/
}
/* get the input text,and send it */
void send_text()
{
GtkTextIter start,end;
gchar *text;
if(issucceed==-1){ /* Haven't create a socket */
show_err("Not connected.../n");
}
else
{ /* Socket creating has succeed ,so send message */
text=(gchar *)malloc(MAXSIZE);
if(text==NULL)
{
printf("Malloc error!/n");
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 there is no input,do nothing but return */
if(strcmp(text,"")!=0)
{
send_func(text);
clean_send_text();
show_local_text(text);
}
else
show_err("The message can not be empty.../n");
free(text);
}
}
/* show errors such as "no input","haven't create sockt" etc. */
void show_err(char *err)
{
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,err,strlen(err));
}
/* get IP address and create socket */
void get_ip(GtkWidget *button,gpointer ip_text)
{
gchar *serv_ip;
int res;
serv_ip=(gchar *)gtk_entry_get_text(GTK_ENTRY((GtkWidget *)ip_text));
res=build_socket(serv_ip);
if(res==1)
show_err("IP Address is  Invalid.../n");
else if(res==-1)
show_err("Connect Failure... /n");/*插入文本到缓冲区*/
else{
show_err("Connect Successful... /n");
issucceed=0;
}
}
/* show the received message */
void show_remote_text(char rcvd_mess[])
{
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,"Server:/n",8);/*插入文本到缓冲区*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,rcvd_mess,strlen(rcvd_mess));/*插入文本到缓冲区*/
gtk_text_buffer_insert(GTK_TEXT_BUFFER(show_buffer),&end,"/n",1);/*插入换行到缓冲区*/
}
/* quit */
void quit_win(GtkWidget *window,gpointer data)
{
gtk_main_quit();
}


makefile代码

OBJ=client.o cl_sock.o

OBJ1=server.o se_sock.o

server:server.o se_sock.o server.h

gcc -Wall $(OBJ1) -o server `pkg-config gtk+-2.0 --libs` -l pthread

server.o:server.c server.h

gcc -Wall -c $< `pkg-config gtk+-2.0 --cflags`

server_sock.o:se_sock.c server.h

gcc -Wall -c $<

client:client.o cl_sock.o client.h

gcc -Wall $(OBJ) -o client `pkg-config gtk+-2.0 --libs` -l pthread

client.o:client.c client.h

gcc -Wall -c $< `pkg-config gtk+-2.0 --cflags`

client_sock.o:cl_sock.c client.h

gcc -Wall -c $<

clean:

rm *.o
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐