select服务端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#define PORT 6666
#define IP "192.168.8.66"
int main(int argc, const char *argv[])
{
int sfd;
if((sfd=socket(AF_INET,SOCK_STREAM,0))<0)//创建流式套接字
{
perror("scoket");
return -1;
}
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
perror("setsockopt");
return -1;
}
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);//端口号的网络字节序
sin.sin_addr.s_addr=inet_addr(IP);//IP号的网络字节序
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
perror("bind");
return -1;
}
if(listen(sfd,128)<0)//把套接字设置为监听状态
{
perror("listen");
return -1;
}
printf("%d",sfd);
//创建一个读集合
fd_set readfds;
fd_set tempfds;//中间集合
//清空集合
FD_ZERO(&readfds);
FD_ZERO(&tempfds);
//将需要的文件描述符加到集合中
FD_SET(0,&readfds);
FD_SET(sfd,&readfds);
int maxfd=sfd;//最大文件描述符
struct sockaddr_in cin;
char buf[128]="";
int s_res=0;
int newfd=0;;
socklen_t len=sizeof(cin);
ssize_t res=0;
struct sockaddr_in tin[1020];
while(1)
{
tempfds=readfds;
if((s_res=select(maxfd+1,&tempfds,NULL,NULL,NULL))<0)//监测中
{
perror("select");
return -1;
}
for(int i=0;i<=maxfd;i++)
{
if(FD_ISSET(i,&tempfds)==0)
{
continue;
}
if(0==i)
{
int sendfd;
int ret;
printf("触发键盘输入事件\n");
ret=scanf("%d %s",&sendfd,buf);
while(getchar()!=10);
if(ret!=2)
{
printf("请重新校验格式\n");
continue;
}
if(strcmp(buf,"quit")==0)
{
exit(0);
}
if(sendfd>sfd&&FD_ISSET(sendfd,&readfds))
{
if(send(sendfd,buf,sizeof(buf),0)<0)
{
perror("send");
return -1;
}
printf("发送成功\n");
}
else
{
printf("该端口不可用\n");
}
}
else if(i==sfd)
{
printf("触发客户端连接事件\n");
if((newfd=accept(sfd,(struct sockaddr *)&cin,&len))<0)//创建新的套接字用来通信
{
perror("accept");
return -1;
}
printf("连接成功newfd=%d\n",newfd);
FD_SET(newfd,&readfds);
maxfd=(maxfd>newfd?maxfd:newfd);
tin[newfd-4]=cin;
}
else
{
bzero(buf,sizeof(buf));
if((res=recv(i,buf,sizeof(buf),0))<0)
{
perror("recv");
return -1;
}
else if(0==res)
{
printf("客户端关闭\n");
FD_CLR(i,&readfds);
close(i);
for(int j=maxfd;j>0;j--)
{
if(FD_ISSET(j,&readfds))
{
maxfd=j;
break;
}
}
}
printf("port=%d %s\n",ntohs(tin[i-4].sin_port),buf);
}
}
}
close(sfd);
close(newfd);
return 0;
}
select客户端
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#define SERPORT 6666
#define SERIP "192.168.8.66"
int main(int argc, const char *argv[])
{
int sfd;
if((sfd=socket(AF_INET,SOCK_STREAM,0))<0)//创建流式套接字
{
perror("scoket");
return -1;
}
struct sockaddr_in cin;
cin.sin_family=AF_INET;//服务器的
cin.sin_port=htons(SERPORT);//端口号的网络字节序
cin.sin_addr.s_addr=inet_addr(SERIP);//IP号的网络字节序
if(connect(sfd,(struct sockaddr *)&cin,sizeof(cin))<0)//建立连接
{
perror("connect");
return -1;
}
//创建集合
fd_set readfds,tempfds;
FD_ZERO(&readfds);
FD_SET(sfd,&readfds);
FD_SET(0,&readfds);
int maxfd=sfd;
ssize_t res;
char buf[128]="";
int ret;
while(1)
{
tempfds=readfds;
//select监测
ret=select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(ret<0)
{
perror("select");
return -1;
}
else if(0==ret)
{
printf("timeout\n");
return -1;
}
if(FD_ISSET(sfd,&tempfds))
{
res=recv(sfd,buf,sizeof(buf),0);//接收
if(res<0)
{
perror("recv");
return -1;
}
else if(0==res)
{
printf("服务端关闭\n");
break;
}
printf("%s\n",buf);
}
if(FD_ISSET(0,&tempfds))
{
bzero(buf,sizeof(buf));//发送
printf("请输入>>>");
scanf("%s",buf);
while(getchar()!=10);
if(send(sfd,buf,sizeof(buf),0)<0)
{
perror("send");
return -1;
}
printf("发送成功\n");
}
}
close(sfd);
return 0;
}
poll客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <poll.h>
#define SERPORT 6666
#define SERIP "192.168.8.66"
int main(int argc, const char *argv[])
{
int sfd;
if((sfd=socket(AF_INET,SOCK_STREAM,0))<0)//创建流式套接字
{
perror("scoket");
return -1;
}
struct sockaddr_in cin;
cin.sin_family=AF_INET;//服务器的
cin.sin_port=htons(SERPORT);//端口号的网络字节序
cin.sin_addr.s_addr=inet_addr(SERIP);//IP号的网络字节序
if(connect(sfd,(struct sockaddr *)&cin,sizeof(cin))<0)//建立连接
{
perror("connect");
return -1;
}
struct pollfd fds[2];//创建集合
fds[0].fd=0;
fds[0].events=POLLIN;//监测读事件
fds[1].fd=sfd;
fds[1].events=POLLIN;
ssize_t res;
char buf[128]="";
int ret;
while(1)//内核循环监测
{
ret=poll(fds,2,-1);
if(ret<0)
{
perror("poll");
return -1;
}
else if(0==ret)
{
printf("timeout\n");
}
//能运行到此处,代表结束阻塞有事件产生
if(fds[0].revents&POLLIN)
{
bzero(buf,sizeof(buf));//发送
printf("请输入>>>");
scanf("%s",buf);
while(getchar()!=10);
if(send(sfd,buf,sizeof(buf),0)<0)
{
perror("send");
return -1;
}
printf("发送成功\n");
}
if(fds[1].revents&POLLIN)
{
res=recv(sfd,buf,sizeof(buf),0);//接收
if(res<0)
{
perror("recv");
return -1;
}
else if(0==res)
{
printf("客户端关闭\n");
break;
}
printf("%s\n",buf);
}
}
close(sfd);
return 0;
}
项目
服务端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
#include <netinet/in.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 6666
#define IP "192.168.8.66"
struct msg
{
int newfd;
struct sockaddr_in sin;
};
char buf[516]="";
void *callback(void*arg);//线程执行体
int upload(int newfd);
int download(int newfd);
int seedir(int newfd);
int main(int argc, const char *argv[])
{
struct msg info;
int sfd,newfd;
if((sfd=socket(AF_INET,SOCK_STREAM,0))<0)//创建流式套接字
{
perror("scoket");
return -1;
}
int reuse=1;
setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);//端口号的网络字节序
sin.sin_addr.s_addr=inet_addr(IP);//IP号的网络字节序
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
perror("bind");
return -1;
}
if(listen(sfd,128)<0)//把套接字设置为监听状态
{
perror("listen");
return -1;
}
struct sockaddr_in cin;//存储连接成功的客户端信息
socklen_t addrlen=sizeof(cin);
pthread_t tid;
while(1)
{
if((newfd=accept(sfd,(struct sockaddr *)&cin,&addrlen))<0)//创建新的套接字用来通信
{
perror("accept");
return -1;
}
info.newfd=newfd;//结构体赋值
info.sin=cin;
printf("[%s:%d] newfd=%d,连接成功\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
if(pthread_create(&tid,NULL,callback,(void*)&info)<0)
{
perror("pthread_create");
return -1;
}
}
close(sfd);
return 0;
}
void *callback(void*arg)//线程执行体
{
pthread_detach(pthread_self());//线程分离
ssize_t res;
int newfd=((struct msg*)arg)->newfd;
while(1)
{
//接收客户端的请求信息
res=recv(newfd,buf,sizeof(buf),0);
if(0==res)
{
printf("客户端已经关闭\n");
close(newfd);
return NULL;
}
else if(res<0)
{
perror("recv");
return NULL;
}
//跳转到对应的功能
switch(buf[1])
{
case 1:
download(newfd);
break;
case 2:
printf("%s\n",buf+2);
upload(newfd);
break;
case 3:
seedir(newfd);
break;
default:
break;
}
}
}
int upload(int newfd)
{
ssize_t res;
int fd;
umask(0);
fd=open(buf+2,O_WRONLY|O_CREAT|O_TRUNC,0777);
if(fd<0)
{
perror("open");
}
*(unsigned short*)buf=htons(5);//操作码
*(unsigned short*)(buf+2)=htons(0);//块编号
if(send(newfd,buf,4,0)<0)//发送ACK
{
perror("send");
return -1;
}
unsigned short num=1;
while(1)
{
bzero(buf,sizeof(buf));
res=recv(newfd,buf,sizeof(buf),0);//接收数据包
if(res<0)
{
perror("recv");
return -1;
}
if(5==buf[1])
{
if(htons(num)==*(unsigned short*)(buf+2))//校验块编号
{
write(fd,buf+4,res-4);
if(res<0)
{
perror("write");
return -1;
}
else if(0==res)
{
printf("文件上传完毕\n");
break;
}
num++;
}
}
if(send(newfd,buf,4,0)<0)//发送ACK
{
perror("send");
return -1;
}
}
close(fd);
}
int download(int newfd)
{
ssize_t res;
int fd;
printf("%s\n",buf+2);
fd=open(buf+2,O_RDONLY);
if(fd<0)
{
perror("open");
*(unsigned short*)buf=htons(6);
if(send(newfd,buf,2,0)<0)
{
perror("sdownload_send");
return -1;
}
return -1;
}
unsigned short num=1;
while(1)
{
bzero(buf,sizeof(buf));
*(unsigned short*)buf=htons(4);//操作码
*(unsigned short*)(buf+2)=htons(num);//块编号
res=read(fd,buf+4,sizeof(buf)-4);
printf("%ld\n",res);
if(send(newfd,buf,res+4,0)<0)
{
perror("sdownload_send");
return -1;
}
if(res<0)
{
perror("read");
return -1;
}
else if(0==res)
{
printf("文件下载完毕\n");
break;
}
//接收ACK
recv(newfd,buf,4,0);
if(htons(num)!=*(unsigned short*)(buf+2))
{
break;
}
num++;
}
close(fd);
}
int seedir(int newfd)
{
DIR *dirp=opendir("./");
bzero(buf,sizeof(buf));
struct dirent *dir;
while(dir!=NULL)
{
dir=readdir(dirp);
if(NULL==dir)
{
break;;
}
strcat(buf,dir->d_name);
buf[strlen(buf)]='\n';
}
if(send(newfd,buf,sizeof(buf),0)<0)
{
perror("send");
return -1;
}
}
客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 6666
#define IP "192.168.8.66"
int upload(int sfd);
int download(int sfd);
int seedir(int sfd);
int main(int argc, const char *argv[])
{
int sfd;
if((sfd=socket(AF_INET,SOCK_STREAM,0))<0)//创建流式套接字
{
perror("scoket");
return -1;
}
struct sockaddr_in cin;
cin.sin_family=AF_INET;//服务器的
cin.sin_port=htons(PORT);//端口号的网络字节序
cin.sin_addr.s_addr=inet_addr(IP);//IP号的网络字节序
if(connect(sfd,(struct sockaddr *)&cin,sizeof(cin))<0)//建立连接
{
perror("connect");
return -1;
}
printf("连接成功\n");
while(1)
{
system("clear");
printf("|****************************|\n");
printf("|*********1.下载*************|\n");
printf("|*********2.上传*************|\n");
printf("|*********3.查看目录*********|\n");
printf("|*********4.退出*************|\n");
printf("|****************************|\n");
printf("请输入>>>");
char c;
c=getchar();
while(getchar()!=10);
switch(c)
{
case '1':
download(sfd);
break;
case '2':
upload(sfd);
break;
case '3':
seedir(sfd);
break;
case '4':
goto END;
break;
default:
printf("输入错误,请重新输入\n");
}
printf("请输入任意字符清屏\n");
while(getchar()!=10);
}
END:
close(sfd);
return 0;
}
int upload(int sfd)
{
char buf[516]="";
char pathname[128]="";
printf("请输入要上传的文件路径>>>");
scanf("%s",pathname);
while(getchar()!=10);
int fd=open(pathname,O_RDONLY);//打开要上传的文件
if(fd<0)
{
perror("fopen");
return -1;
}
char filename[128]="";
int i;
int k=0;
for(i=strlen(pathname);i>0;i--)
{
if(pathname[i]!='/')
{
k++;
}
else
{
break;
}
}
strcpy(filename,pathname+(strlen(pathname)-k)+1);
size_t res;
int size=sprintf(buf,"%c%c%s",0,2,filename);//上传请求包
if(send(sfd,buf,size,0)<0)
{
perror("send");
return -1;
}
unsigned short num=0;
int flag=0;
while(1)
{
//接收ACK包
if((recv(sfd,buf,sizeof(buf),0))<0)
{
perror("recv");
return -1;
}
if(htons(num)==*(unsigned short*)(buf+2))
{
printf("%d %d\n",htons(num),*(unsigned short*)(buf+2));
if(0==flag)
{
fd=open(filename,O_RDONLY);
if(fd<0)
{
perror("open");
return -1;
}
flag=1;
}
num++;
bzero(buf,sizeof(buf));
res=read(fd,buf+4,sizeof(buf)-4);
printf("%ld\n",res);
*(unsigned short*)buf=htons(5);//操作码
*(short int*)(buf+2)=htons(num);//块编号
if(send(sfd,buf,res+4,0)<0)
{
perror("send");
return -1;
}
if(0==res)
{
break;
}
else if(res<0)
{
return -1;
}
}
}
close(fd);
}
int download(int sfd)
{
ssize_t res;
char buf[516]="";
char filename[128]="";
printf("请输入要下载的文件名>>>");
scanf("%s",filename);
while(getchar()!=10);
int size=sprintf(buf,"%c%c%s",0,1,filename);//下载请求包
if(send(sfd,buf,size,0)<0)
{
perror("send");
return -1;
}
int flag=0;
int fd;
while(1)
{
bzero(buf,sizeof(buf));
if((res=recv(sfd,buf,sizeof(buf),0))<0)
{
perror("recv");
return -1;
}
if(0==flag)
{
fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0777);
if(fd<0)
{
perror("open");
return -1;
}
flag=1;
}
int asd=write(fd,buf+4,res-4);
printf("%ld %d\n",res,asd);
//发送ACK包
buf[1]=5;
printf("%d\n",*(unsigned short*)(buf+2));
if(send(sfd,buf,4,0)<0)
{
perror("send");
return -1;
}
if(res<516&&res>=0)
{
break;
}
}
close(fd);
}
int seedir(int sfd)
{
char buf[516]="";
int size=sprintf(buf,"%c%c",0,3);//查看请求包
if(send(sfd,buf,size,0)<0)
{
perror("send");
return -1;
}
bzero(buf,sizeof(buf));
if(recv(sfd,buf,sizeof(buf),0)<0)
{
perror("recv");
return -1;
}
printf("%s",buf);
}