汇编指令合集
用select实现服务器并发代码
#include<myhead.h>
#define IP "192.168.0.106"
#define PORT 8888
int main(int argc, const char *argv[])
{
//新建套接字文件
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("socket success\n");
//允许端口快速的被复用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("port reuse enable\n");
//填充地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(IP);
sin.sin_port = htons(PORT);
//bind函数绑定地址
if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
//设置sfd为监听套接字
if(listen(sfd, 128) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("listen success\n");
fd_set readfds, tempfds; //定义文件描述符集合
FD_ZERO(&readfds); //清空readfds
FD_SET(0, &readfds); //将文件描述符0添加到集合中
FD_SET(sfd, &readfds); //将文件描述符sfd添加到集合中
int maxfd = sfd; //定义最大文件描述符
char buf[128] = ""; //定义容器存放字符串
struct sockaddr_in cin; //定义地址结构体存放accept所接收到的客户端的地址信息
socklen_t cin_len = sizeof(cin); //定义结构体大小
ssize_t rcv_len = -1; //定义接收的字节大小
struct sockaddr_in savecin[1024];//定义存放客户端信息的结构体数组,每有一个cin被接受,\
都会存入下标为newfd的数组中
while(1)
{
tempfds = readfds;
if(select(maxfd+1, &tempfds, NULL, NULL, NULL) < 0)
{
ERR_MSG("select");
return -1;
}
for(int i=0; i<=maxfd; i++) //遍历文件描述符,若有文件描述符就绪,则运行对应的处理函数
{
if((FD_ISSET(i, &tempfds)) == 0)
{
continue;
}
if(0 == i)
{
printf("触发键盘输入事件\n");
bzero(buf, sizeof(buf));
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf)-1] = '\0';
printf("你输入了%s\n", buf);
}else if(sfd == i)
{
printf("触发客户端连接事件\n");
//执行accept函数
int newfd = accept(sfd, (struct sockaddr*)&cin, &cin_len);
if(newfd < 0)
{
ERR_MSG("accept");
break;
}
printf("client[%s:%d] connected newfd = %d\n", inet_ntoa(cin.sin_addr),\
ntohs(cin.sin_port), newfd);
FD_SET(newfd ,&readfds); //将accept函数创建的newfd加入到readfds集合中
savecin[newfd] = cin;
maxfd = maxfd>newfd?maxfd:newfd; //更新maxfd的值
}else //当文件描述符不是sfd和0时,进行客户端交互事件
{
printf("触发客户端交互事件\n");
bzero(buf, sizeof(buf)); //清空buf防止有残留数据
//接受数据
rcv_len = recv(i, buf, sizeof(buf), 0);
if(rcv_len < 0)
{
ERR_MSG("recv");
break;
}else if(rcv_len == 0)
{
printf("客户端已下线\n");
close(i); //关闭与该客户端交互的对应的文件描述符
FD_CLR(i, &readfds); //将该文件描述符从集合中踢出
//更新maxfd
for(; maxfd>=sfd; maxfd--)
{
if(FD_ISSET(maxfd, &readfds))
{
break;
}
}
break;
}else
{
printf("client[%s:%d] rcvdata = %s newfd = %d\n",\
inet_ntoa(savecin[i].sin_addr),\
ntohs(savecin[i].sin_port), buf, i);
}
//发送数据
strcat(buf, ">_<");
if(send(i, buf, sizeof(buf), 0) < 0)
{
ERR_MSG("send");
break;
}
printf("send success data = %s\n", buf);
}
}
}
if(close(sfd) < 0)
{
ERR_MSG("close");
return -1;
}
return 0;
}