作业
1> 使用select完成TCP客户端程序
//client
#include<myhead.h>
#define CLINET_IP "192.168.125.79"
#define CLINET_PORT 9999
#define SERVE_IP "192.168.125.79"
#define SERVE_PORT 8888
int main(int argc, const char *argv[])
{
//socket()
int cfd=-1;
if((cfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket error");
return -1;
}
printf("cfd=%d\n",cfd);
int reuse=1;
if(setsockopt(cfd, SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
{
perror("setsockopt error");
return -1;
}
//(bind())
struct sockaddr_in cin;
cin.sin_family=AF_INET;
cin.sin_port=htons(CLINET_PORT);
cin.sin_addr.s_addr=inet_addr(CLINET_IP);
if(bind(cfd,(struct sockaddr*)&cin,sizeof(cin))==-1)
{
perror("bind error");
return -1;
}
printf("[%s:%d]->绑定成功\n",CLINET_IP,CLINET_PORT);
//connect()
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(SERVE_PORT);
sin.sin_addr.s_addr=inet_addr(SERVE_IP);
if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("connect error");
return -1;
}
printf("[%s:%d]->连接成功\n",SERVE_IP,SERVE_PORT);
//recv()/send()
char buf[128]="";
fd_set readfds;//定义文件描述符集合
FD_ZERO(&readfds);//清空集合
FD_SET(0,&readfds);//放入集合
FD_SET(cfd,&readfds);//放入集合
int res1=-1;//接收select返回
int res2=-1;//接收recv返回
fd_set tempfds;//定义一个临时文件描述符集合
while(1)
{
tempfds=readfds;
res1=select(cfd+1,&tempfds,NULL,NULL,NULL);
if(res1==-1)
{
perror("select error");
return -1;
}
else if(res1==0)
{
printf("time out\n");
return -1;
}
if(FD_ISSET(0,&tempfds))
{
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
send(cfd,buf,sizeof(buf),0);
}
if(FD_ISSET(cfd,&tempfds))
{
bzero(buf,sizeof(buf));
res2=recv(cfd,buf,sizeof(buf),0);
if(res2==0||strcmp(buf,"quit")==0)
{
printf("服务器下线\n");
break;
}
printf("[%s:%d]->%s\n",SERVE_IP,SERVE_PORT,buf);
}
}
//close()
close(cfd);
return 0;
}
//serve
#include<myhead.h>
#define PORT 8888
#define IP "192.168.125.79"
int main(int argc, const char *argv[])
{
int sfd=-1;
if((sfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket error");
return -1;
}
printf("sfd=%d\n",sfd);
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
{
perror("setsockopt error");
return -1;
}
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
sin.sin_addr.s_addr=inet_addr(IP);
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind error");
return -1;
}
printf("bind success _%d_%s_%s\n",__LINE__,__FILE__,__func__);
if(listen(sfd,128)==-1)
{
perror("listen error");
return -1;
}
printf("listen success _%d_%s_%s\n",__LINE__,__FILE__,__func__);
struct sockaddr_in cin;
socklen_t socklen=sizeof(cin);
fd_set readfds; //定义阻塞的文件描述符集合
FD_ZERO(&readfds); //清空
FD_SET(sfd,&readfds); //将文件描述符放入
FD_SET(0,&readfds);
int res=0;//select返回值
int maxfd=sfd;
int newfd=-1;
char buf[128]="";
char rbuf[128]="";//服务器客户端通信
struct sockaddr_in arr_cin[1024];
fd_set tempfds;
while(1)
{
tempfds=readfds;
res=select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(res==-1)
{
perror("select error");
return -1;
}
else if(res ==0)
{
printf("time out\n");
return -1;
}
else
{
for(int index=0;index<=maxfd;index++)
{
if(!FD_ISSET(index,&tempfds))//所有文件描述符没有事件发生
{
continue;
}
else if( index==sfd )
{
if((newfd=accept(sfd,(struct sockaddr*)&cin,&socklen))==-1)
{
perror("accept error");
return -1;
}
arr_cin[newfd]=cin;
printf("[%s:%d]:连接成功,newfd=%d\n",inet_ntoa(arr_cin[index].sin_addr),ntohs(arr_cin[index].sin_port),newfd);
FD_SET(newfd,&readfds);//新的newfd应当加入原本的readfds
if(newfd>maxfd)
{
maxfd=newfd;
}
}
else if( index==0 )
{
scanf("%s",buf);
printf("将发送所有连接的用户->%s\n",buf);
for(int j=4;j<=maxfd;j++)
{
send(j,buf,sizeof(buf),0);
}
}
else
{
bzero(rbuf,sizeof(rbuf));
if(recv(index,rbuf,sizeof(rbuf),0)==0)
{
printf("客户端下线\n");
close(index);//关闭套接字文件
FD_CLR(index,&tempfds);//移除select数组
for(int i=maxfd;i>0;i--)
{
if(FD_ISSET(i,&readfds))
{
maxfd=i;
break;
}
}
continue;
}
printf("[%s:%d]:%s\n",inet_ntoa(arr_cin[index].sin_addr),ntohs(arr_cin[index].sin_port),rbuf);
strcat(rbuf,"^_^");
send(index,rbuf,sizeof(rbuf),0);
}
}
}
}
close(sfd);
return 0;
}
2> 使用poll完成TCP并发服务器