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;
}