posts - 13, comments - 0, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

linux 下 实现一个简单的通信程序

Posted on 2010-12-29 17:02 午夜凉饭 阅读(377) 评论(0)  编辑 收藏 引用 所属分类: Linux
用到了select,对select的了解更加深入了一些。
由于使用到了tcp链接,所以在发送的时候一定要关闭socket以使对端能收到EOF。

#include <sys/types.h>
#include <ctype.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#include <net/route.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <dlfcn.h>
#define LISTEN_PORT 25000
#define BUFFLEN 128
typedef struct Recv_Info
{
    FILE * fconnectin;
    char filepath[50];
}Recv_Info;
typedef struct Send_Info
{
    char ip[50];
    char filepath[50];
}Send_Info;

int listen_fd,connect_fd;
void handle_int ( int signo )
{
    fprintf ( stderr, "Interrupt catched!!\n" );       
   
    exit(0);   
   
}
static void* recieve_file(void * arg)
{
   
    Recv_Info *recv_info = (Recv_Info*)arg;   
    FILE * p;
    p=fopen(recv_info->filepath,"w+");
    if(p==NULL)
        fprintf(stdout,"Fopen failed in recieve file! make sure your filepath is right!\n");
           
    char buff[BUFFLEN];       
    int count=0;
    int amount=0;
    while(fgets(buff,BUFFLEN,recv_info->fconnectin)!=NULL)
    {   
        count=strlen(buff);
        amount+=count;
        fputs(buff,p);       
    }       
    fprintf(stdout,"Recieve %d Bytes !\n",amount);       
    fclose(p);
    close(connect_fd);
   
}
static void* send_file(void * arg)
{
    Send_Info * send_info=(Send_Info *)arg;
   
    char buff[BUFFLEN];
    int remote_fd;
    int remote_len;
    struct sockaddr_in remote;           
   
    FILE * p;
    p=fopen(send_info->filepath,"r+");
   
    if(p==NULL)
    {
        fprintf(stdout,"fopen failed!\n");
        return NULL;
    }
    remote_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (remote_fd == -1)
    {
        fprintf(stderr, "socket() apply failed!\n");
        return NULL;
    }   
    memset(&remote, 0, sizeof(remote));
    remote.sin_family      = AF_INET;
    remote.sin_port        = htons(LISTEN_PORT);
    remote.sin_addr.s_addr = inet_addr(send_info->ip);   
    int count = 0;
    int amount = 0;
    if(connect(remote_fd,(sockaddr*)&remote,sizeof(sockaddr_in))==0)
    {       
        send(remote_fd,"s",1,0);
        while(fgets(buff,BUFFLEN,p)!=NULL)
        {
            count=send(remote_fd,buff,strlen(buff),0);
            amount+=count;           
        }
        fprintf(stdout,"Send %d Bytes !\n",amount);       
    }
    else
    {
        fprintf(stderr,"errno:%d",errno);
    }
    fclose(p);
    close(remote_fd);
}
int main(int argc, char *argv[])
{       
    //init socket
    struct sockaddr_in local;
    int remote_len;
    struct sockaddr_in remote;       
    int ret;   
    pthread_t tid;
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd == -1)
    {
        fprintf(stderr, "socket() apply failed!\n");
        return NULL ;
    }   
    memset(&local, 0, sizeof(local));
    local.sin_family      = AF_INET;
    local.sin_port        = htons(LISTEN_PORT);
    local.sin_addr.s_addr = htonl(INADDR_ANY);
   
    if (bind(listen_fd, (struct sockaddr *)&local, sizeof(local)) == -1)
    {
        fprintf(stderr, "bind failed!\n");
        close(listen_fd);
        return NULL;
    }   
    if (listen(listen_fd, 5) == -1)
    {
        fprintf(stderr, "listen wrong!\n");
        close(listen_fd);       
        return -1;
    }
    //init signal
    struct sigaction act;
    act.sa_handler = handle_int;
    sigemptyset ( &act.sa_mask );
    act.sa_flags = 0;
    sigaction ( SIGINT, &act, NULL );
    //////////////////
    //message loop   
    fprintf(stdout,"-Welcome to FeiGe! q to quit ,s filename ip to send ,p to input path-\n");   
   
    //init select
    fd_set rfds;   
    int retval;

    FD_ZERO(&rfds);
    FD_SET(0, &rfds);     
    FD_SET(listen_fd, &rfds);     
   
    char buffstdin[100];
    char * token;
    FILE * fstdin;
    Recv_Info recv_info; //used for recv thread
    Send_Info send_info; //used for send thread
   
    fstdin=fdopen(0,"r+");
    while ((retval = select(4, &rfds, NULL, NULL, NULL)) > 0)//begin the select loop
    {       
        if(FD_ISSET(0,&rfds))//stdin is ready
        {
            fgets(buffstdin,100,fstdin);        //get input
            switch(buffstdin[0])                //check the first charactor
            {
                case 'q':
                {
                    exit(0);
                    break;
                }
                case 's':                        //s means send
                {                   
                    memset(&send_info,0,sizeof(Send_Info));
                    token = strtok(buffstdin," "); // s
                    token = strtok(NULL," "); // filename
                    memcpy(send_info.filepath,token,strlen(token));
                    token = strtok(NULL,"\n"); // ip
                    memcpy(send_info.ip,token,strlen(token));                   
                    if ((ret = pthread_create(&tid, NULL, send_file, (void *)&send_info)) != 0)
                    {
                        fprintf(stderr, "pthread_create() failed!\n");
                        close(connect_fd);
                    }                   
                    break;
                }
                case 'p':                            //p means path
                {                   
                    token = strtok(buffstdin," ");     // get a p
                    token = strtok(NULL,"\n");         // get path                   
                    memcpy(recv_info.filepath,token,strlen(token));
                    if ((ret = pthread_create(&tid, NULL, recieve_file, (void *)&recv_info)) != 0)
                    {
                        fprintf(stderr, "pthread_create() failed!\n");
                        close(connect_fd);
                    }
                    break;                   
                }
                default:
                    break;               
            }       
        }       
        if(FD_ISSET(listen_fd,&rfds))//listen fd is ready
        {           
            remote_len = sizeof(remote);
            memset(&remote, 0, sizeof(remote));
            connect_fd = accept(listen_fd, (struct sockaddr *)&remote, (socklen_t *)&remote_len);
            if (connect_fd == -1)
            {
                if (errno == EINTR)
                    continue;
                fprintf(stderr, "accept failed!\n");
                close(listen_fd);           
                return -1;
            }
            memset(&recv_info,0,sizeof(Recv_Info));           
            recv_info.fconnectin=fdopen(connect_fd,"r+");
            if(fgetc(recv_info.fconnectin)!='s')
            {
                close(connect_fd);
                fprintf(stdout,"wrong format file incoming!\n");
            }
            else
                fprintf(stdout,"A new file ,input a full path with p \n");           
        }
        FD_ZERO(&rfds);
        FD_SET(0, &rfds);   
        FD_SET(listen_fd, &rfds);       
    }     
    return 0;
}

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理