Chinaunix首页 | 论坛 | 博客
  • 博客访问: 523045
  • 博文数量: 118
  • 博客积分: 10028
  • 博客等级: 上将
  • 技术积分: 1820
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-07 18:46
文章分类

全部博文(118)

文章存档

2009年(12)

2008年(106)

我的朋友

分类: C/C++

2008-10-13 21:36:57


不能叫改版,因为没版本之说~
和chkmail一样,改了文件结构,改了一些不必要的东西,加了一些有必要的东西,注释换成英文~
原版在此:http://blog.chinaunix.net/u1/53217/showart_441186.html

依然是server无界面~

有这几个文件:serever.c client.c client.h cl_sock.c makefile

看代码吧~(最后可下载压缩包)

server.c
 

/*************************************************
 * server.c *
 * Function: *
 * receive message from client and print it *
 * send message to client *
 *************************************************/


#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 PORT 8888
#define MAXSIZE 1024

int sockfd;
struct sockaddr_in saddr,caddr;
socklen_t len=sizeof(caddr);

/* 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)
        {
            perror("server recv error");
            exit(1);
        }
        printf("%s: %s \n",inet_ntoa(*(struct in_addr*)&caddr.sin_addr),recv_text);
    }
}

/* Send function,send message to client */
void send_func()
{
    char send_text[MAXSIZE];

    while(1)
    {
        bzero(send_text,MAXSIZE);
        fgets(send_text,MAXSIZE,stdin);

        /* If there is no text,continue */
        if(strlen(send_text)==1)
            continue;
        /* Send message */    
        if(sendto(sockfd,send_text,strlen(send_text),0,(struct sockaddr*)&caddr,len)<0)
        {
            perror("S send error");
            exit(1);
        }
        
    }
}

int main(int argc,char **argv)
{
    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);
    }

    /* Create a socket */
    if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)
    {
        perror("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)
    {
        perror("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)
    {
        perror("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)
    {
        perror("Thread create error");
        exit(EXIT_FAILURE);
    }

    /* Callback the attribute of thread */
    (void)pthread_attr_destroy(&thread_attr);

    /* Call send_func */
    send_func();
    return 0;
}



client.c

/*********************************
 * Client.c *
 * Function: *
 * create the chat window *
 *********************************/


#include "client.h"
#include <gtk/gtk.h>

extern int sockfd;
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;
    GtkWidget *hbox,*vbox;
    GtkWidget *scrolled1,*scrolled2;

    gtk_init(&argc,&argv);
    window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title(GTK_WINDOW(window),"Free Chat -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("连接");
    send_button=gtk_button_new_with_label("发送");
    quit_button=gtk_button_new_with_label("关闭");
    
    /* 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);

    /* 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),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,"我说:\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);/*插入文本到缓冲区*/
}

/* 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(sockfd==-1){ /* Haven't create a socket */
         show_err("未建立链接...\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("消息不能为空...\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地址无效...\n");
    else if(res==-1)
        show_err("链接失败... \n");/*插入文本到缓冲区*/
    else
        show_err("连接成功... \n");
}

/* 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,"他说:\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);/*插入换行到缓冲区*/
}

/* 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=-1;
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);
    }
}


makefile


OBJ=client.o cl_sock.o

server:server.c
    gcc -Wall server.c -o server -l pthread
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


文件:chat.rar
大小:4KB
下载:下载


阅读(1212) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~