作业要求:
1> 将白天课堂代码重新实现一遍:
select实现的TCP并发服务器
poll实现的TCP客户端
2> 君子作业
select实现的TCP客户端
poll实现的TCP并发服务器
作业1:
运行代码:
select实现的TCP并发服务器
#include<myhead.h>
#define SER_IP "192.168.117.111"
#define SER_PORT 8888
int main(int argc, const char *argv[])
{
//1.创建套接字sfd
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(-1==sfd){
perror("socket error");
return -1;
}
printf("socket success:sfd = %d\n",sfd);
//端口快速重用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){
perror("reuse error");
return -1;
}
printf("reuse success\n");
//2.绑定bind
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))==-1){
perror("bind error");
return -1;
}
printf("bind success \n");
//3.开启监听
if(listen(sfd,128)==-1){
perror("listen error");
return -1;
}
printf("listen success\n");
//4
struct sockaddr_in cin;
socklen_t socklen = sizeof(cin);
//堵塞文件设置select
fd_set readfd,tempfd;
FD_ZERO(&readfd);
FD_SET(0,&readfd);//放入输入文件
FD_SET(sfd,&readfd);//放入sfd
int maxfd=sfd;
int newfd;
struct sockaddr_in cin_arr[1024];//存放客户端信息
char sbuf[128]="";
while(1){
tempfd = readfd;
int res = select(maxfd+1,&tempfd,NULL,NULL,NULL);//筛选tempfd
if(res==0){
continue;
}else if(res = 0){
perror("select error");
return -1;
}
/********************************/
for(int i = 0;i<=maxfd;i++){
//接受连接请求
if(!(FD_ISSET(i,&tempfd))){
continue;
}
if(i==sfd){
if(FD_ISSET(sfd,&tempfd)){
if((newfd = accept(sfd,(struct sockaddr *)&cin,&socklen))==-1){
perror("accept error");
return -1;
}
printf("[%s %d]发来请求\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
FD_SET(newfd,&readfd);//将newfd加入检测数组
if(newfd>maxfd){
maxfd = newfd;
}
cin_arr[newfd]=cin;//cin放入数组
}
/**********************************/
}else if(i==0){
//输入设置
if(FD_ISSET(0,&tempfd)){
bzero(sbuf,sizeof(sbuf));
fgets(sbuf,sizeof(sbuf)-1,stdin);
sbuf[strlen(sbuf)-1]=0;
for(int j=4;j<=maxfd;j++){
if(FD_ISSET(j,&readfd)){
send(j,sbuf,strlen(sbuf),0);
printf("发送成功\n");
}
}
}
/***********************************/
}else if(i>3){
//接受客户端信息
if(FD_ISSET(i,&tempfd)){
bzero(sbuf,sizeof(sbuf));
int ret = recv(i,sbuf,sizeof(sbuf)-1,0);
if(ret <=0){
printf("对方已下线\n");
//除去客户端的文件描述符
FD_CLR(i,&readfd);
close(i);
if(i==maxfd){
for(int j=maxfd-1;j>=3;j--){
if(FD_ISSET(j,&readfd)){
maxfd = j;
break;
}
}//for
}//if
continue;
}//if
printf("[%s %d]>>>%s\n",inet_ntoa(cin_arr[i].sin_addr),htons(cin_arr[i].sin_port),sbuf);
strcat(sbuf,"*<*");
send(i,sbuf,strlen(sbuf),0);
}//if
}//i>3
/************************************/
}//for
}
//关闭文件
close(sfd);
return 0;
}
poll实现的TCP客户端
#include<myhead.h>
#define SER_IP "192.168.1.101"
#define SER_PORT 8888
int main(int argc, const char *argv[])
{
//1.创建套接字cfd
int cfd = socket(AF_INET,SOCK_STREAM,0);
if(-1==cfd){
perror("socket error");
return -1;
}
printf("socket success:cfd = %d\n",cfd);
//连接
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
//堵塞文件设置pfd
struct pollfd pfd[2];
pfd[0].fd=0;
pfd[0].events=POLLIN;
pfd[1].fd=cfd;
pfd[1].events=POLLIN;
char cbuf[128]="";
//连接
if(connect(cfd,(struct sockaddr *)&sin,sizeof(sin))==-1){
perror("connect error");
return -1;
}
printf("connect success\n");
while(1){
int res = poll(pfd,2,-1);
if(res==0){
continue;
}else if(res = 0){
perror("select error");
return -1;
}
//输入设置
if(pfd[0].revents==POLLIN){
bzero(cbuf,sizeof(cbuf));
fgets(cbuf,sizeof(cbuf)-1,stdin);
cbuf[strlen(cbuf)-1]=0;
send(cfd,cbuf,strlen(cbuf),0);
}
/***********************************/
//接受客户端信息
if(pfd[1].revents==POLLIN){
bzero(cbuf,sizeof(cbuf));
int ret = recv(cfd,cbuf,sizeof(cbuf),0);
if(ret <= 0){
printf("服务器已下线\n");
return 0;
}
printf("服务器发来>>>%s\n",cbuf);
}
}
//关闭文件
close(cfd);
return 0;
}
运行截图:
作业2:
运行代码:
#include<myhead.h>
#define SER_IP "192.168.1.101"
#define SER_PORT 8888
int main(int argc, const char *argv[])
{
//1.创建套接字cfd
int cfd = socket(AF_INET,SOCK_STREAM,0);
if(-1==cfd){
perror("socket error");
return -1;
}
printf("socket success:cfd = %d\n",cfd);
//连接
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
//堵塞文件设置select
fd_set readfd,tempfd;
FD_ZERO(&readfd);
FD_SET(0,&readfd);//放入输入文件
FD_SET(cfd,&readfd);//放入cfd
char cbuf[128]="";
//连接
if(connect(cfd,(struct sockaddr *)&sin,sizeof(sin))==-1){
perror("connect error");
return -1;
}
printf("connect success\n");
while(1){
tempfd = readfd;
int res = select(cfd+1,&tempfd,NULL,NULL,NULL);//筛选tempfd
if(res==0){
continue;
}else if(res = 0){
perror("select error");
return -1;
}
//输入设置
if(FD_ISSET(0,&tempfd)){
bzero(cbuf,sizeof(cbuf));
fgets(cbuf,sizeof(cbuf)-1,stdin);
cbuf[strlen(cbuf)-1]=0;
send(cfd,cbuf,strlen(cbuf),0);
}
/***********************************/
//接受客户端信息
if(FD_ISSET(cfd,&tempfd)){
bzero(cbuf,sizeof(cbuf));
recv(cfd,cbuf,sizeof(cbuf),0);
printf("服务器发来>>>%s\n",cbuf);
}
}
//关闭文件
close(cfd);
return 0;
}
poll实现的TCP并发服务器
#include<myhead.h>
#define SER_IP "192.168.1.101"
#define SER_PORT 8888
int main(int argc, const char *argv[])
{
//1.创建套接字sfd
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(-1==sfd){
perror("socket error");
return -1;
}
printf("socket success:sfd = %d\n",sfd);
//端口快速重用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){
perror("reuse error");
return -1;
}
printf("reuse success\n");
//2.绑定bind
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))==-1){
perror("bind error");
return -1;
}
printf("bind success \n");
//3.开启监听
if(listen(sfd,128)==-1){
perror("listen error");
return -1;
}
printf("listen success\n");
//4
struct sockaddr_in cin;
socklen_t socklen = sizeof(cin);
//堵塞文件设置poll
struct pollfd pfd[1024];
pfd[0].fd = 0;
pfd[0].events=POLLIN;
pfd[1].fd = sfd;
pfd[1].events=POLLIN;
int newfd;
int num=2;
struct sockaddr_in cin_arr[1024];//存放客户端信息
char sbuf[128]="";
while(1){
//设置堵塞
int res = poll(pfd,num,-1);
if(res==0){
continue;
}else if(res == 0){
perror("select error");
return -1;
}
/********************************/
for(int i = 0;i<num;i++){
//接受连接请求
if(!(pfd[i].revents==POLLIN)){
continue;
}
if(i==1){
if(pfd[i].revents==POLLIN){
if((newfd = accept(sfd,(struct sockaddr *)&cin,&socklen))==-1){
perror("accept error");
return -1;
}
printf("[%s %d]发来请求\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
pfd[num].fd=newfd;//将newfd加入检测数组
pfd[num].events=POLLIN;
cin_arr[newfd]=cin;//cin放入数组
num++;
}
/**********************************/
}else if(i==0){
//输入设置
if(pfd[0].revents==POLLIN){
bzero(sbuf,sizeof(sbuf));
fgets(sbuf,sizeof(sbuf)-1,stdin);
sbuf[strlen(sbuf)-1]=0;
for(int j=2;j<=num;j++){
if(pfd[j].events==POLLIN){
send(pfd[j].fd,sbuf,strlen(sbuf),0);
}
}
printf("发送成功\n");
}
/***********************************/
}else if(i>=2){
//接受客户端信息
if(pfd[i].revents==POLLIN){
bzero(sbuf,sizeof(sbuf));
int ret = recv(pfd[i].fd,sbuf,sizeof(sbuf)-1,0);
if(ret <=0){
printf("对方已下线\n");
//除去客户端的文件描述符
close(pfd[i].fd);
if(i==num-1){
num--;
}else{
pfd[i]=pfd[num-1];
num--;
}
continue;
}//if
printf("[%s %d]>>>%s\n",inet_ntoa(cin_arr[pfd[i].fd].sin_addr),htons(cin_arr[pfd[i].fd].sin_port),sbuf);
strcat(sbuf,"*<*");
send(pfd[i].fd,sbuf,strlen(sbuf),0);
}//if
}//i>3
/************************************/
}//for
}
//关闭文件
close(sfd);
return 0;
}