Hello World
#include <iostream>
#include <strings.h>
#include <cstring>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 8001
#define MESSAGE_LEN 1024
#define FD_SIZE 1024
int main(int argc, char* argv[])
{
int ret = -1;
int on = 1;
int backlog = 10; // 缓冲长度
int socket_fd, accept_fd;
struct sockaddr_in serveraddr, clientaddr;
char in_buff[MESSAGE_LEN] = {'\0'};
pid_t pid;
int flags; // fcntl函数返回值
int events = 0;
int max_fd = -1;
fd_set fd_sets;
int accept_fds[FD_SIZE] = {'\0'};
int curpos = -1;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd == -1){
std::cout <<"Failed to create socket!\n";
exit(-1);
}
flags = fcntl(socket_fd,F_GETFL,0);
fcntl(socket_fd,F_SETFL,flags | O_NONBLOCK); // 设置为非阻塞
max_fd = socket_fd;
// 这段代码的主要目的是确保套接字可以快
// 速地重新使用相同的地址和端口,通常用
// 于在服务器程序中,以便服务器能够更快
// 地重新启动或者处理新的连接。
ret = setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
if (ret == -1){
std::cout <<"Failed to set socket options!\n";
}
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = PORT;
serveraddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(serveraddr.sin_zero), 8);
ret = bind(socket_fd, (struct sockaddr*)&serveraddr,sizeof(struct sockaddr));
if (ret == -1){
std::cout <<"Failed to bind addr!\n";
exit(-1);
}
ret = listen(socket_fd, backlog);
if (ret == -1){
std::cout <<"Failed to listen addr!\n";
exit(-1);
}
int col = 0;
for (;;){
FD_ZERO(&fd_sets);
FD_SET(socket_fd,&fd_sets);
for (int i = 0; i < FD_SIZE; i ++ ){
if (accept_fds[i] != 0){
if (accept_fds[i] > max_fd){
max_fd = accept_fds[i];
}
FD_SET(accept_fds[i], &fd_sets);
}
}
// 文件描述符就绪的个数
/*无限期阻塞,并测试文件描述符变动 */
events = select(max_fd + 1,&fd_sets,nullptr,nullptr,nullptr);
if (events < 0){
std::cout <<"Using select error!\n";
break;
}else if (events == 0){
std::cout <<"timeout...\n";
continue;
}else if (events){
if (FD_ISSET(socket_fd, &fd_sets)){ // 侦听,来连接了
curpos = -1;
for (int i = 0; i < FD_SIZE; i ++ ){
if (accept_fds[i] == 0){ // 查找一个空位
curpos = i;
break;
}
}
if (curpos == -1){
std::cout <<"new client is failed to add!\n";
continue;
}
socklen_t addr_len = sizeof(struct sockaddr);
accept_fd = accept(socket_fd,(struct sockaddr*)&clientaddr,&addr_len);
flags = fcntl(accept_fd,F_GETFL,0);
fcntl(accept_fd,F_SETFL,flags | O_NONBLOCK); // 设置为非阻塞
accept_fds[curpos] = accept_fd;
}
for (int i = 0; i < FD_SIZE; i++){
if (accept_fds[i] != 0 && FD_ISSET(accept_fds[i], &fd_sets)){ // 开始读数据
memset(in_buff, 0, MESSAGE_LEN);
ret = recv(accept_fds[i],in_buff,MESSAGE_LEN, 0);
if(ret > 0) // 接受数据成功
{
// printf("message form client[%d]:%s\n", i, resv_message);
std::cout <<"----- 信息 "<< ++ col <<" -----\n";
std::cout <<"客户端发来的数据: "<< in_buff <<'\n';
std::string str = in_buff;
str = "!@#$%^&*- " + str + " -*&^%$#@!";
send(accept_fds[i],str.c_str(),MESSAGE_LEN,0);
}
else if(ret < 0) // 接收失败
{
printf("rescessed error!");
}
//某个客户端退出
else //cancel fdset and set fd = 0
{
FD_CLR(accept_fds[i], &fd_sets);
accept_fds[i] = 0;
continue; //这里如果用break的话一个客户端退出会造成服务器也退出。
}
}
}
}
}
close(socket_fd);
return 0;
}