#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
using namespace std;
// uint32_t htonl(uint32_t hostlong);
// 将32位的数据从主机字节序转换为网络字节序
// in_addr.saddr = htonl(INADDR_ANY)
// uint16_t htons(uint16_t hostshort);
// 将16位的数据从主机字节序转换为网络字节序
// uint32_t ntohl(uint32_t netlong);
// 将32位的数据从网络字节序转换为主机字节序
// uint16_t ntohs(uint16_t netshort);
// 将16位的数据从网络字节序转换为主机字节序
#define MAX_CLIENT_COUNT 16
struct Client_Socket_IPPort {
int hSocket;
uint32_t uIPAddress;
uint16_t uPort;
};
void printhost(struct hostent *host)
{
char **aliases = NULL;
char **addr_list = NULL;
char addr_p[INET_ADDRSTRLEN]; // IPv4
/* print host name and aliases */
printf("hostname: %s\n", host->h_name);
for(aliases = host->h_aliases; *aliases; aliases++)
{
printf("alternate name: %s\n", *aliases);
}
/* print address type and length */
if(host->h_addrtype == AF_INET)
{
printf("address type: AF_INET\n");
}
else
{
printf("Not an IPv4 address.\n");
}
printf("address length: %d\n", host->h_length);
/* print address list */
printf("%x\n", *(int *)(*(host->h_addr_list)));
for(addr_list = host->h_addr_list; *addr_list; addr_list++)
{
printf("address: %s\n", inet_ntop(host->h_addrtype, *addr_list, addr_p, INET_ADDRSTRLEN));
}
}
void printclient(Client_Socket_IPPort client[]) {
cout << "client list: " << endl;
int nIndex = 0;
for (int i=0; i<MAX_CLIENT_COUNT; i++) {
if (client[i].hSocket <= 0) {
continue;
}
cout << nIndex << ": ip address: ";
uint32_t uClientIPAddress = client[i].uIPAddress;
cout << ((uClientIPAddress & 0xff000000) >> 24);
cout << ".";
cout << ((uClientIPAddress & 0x00ff0000) >> 16);
cout << ".";
cout << ((uClientIPAddress & 0x0000ff00) >> 8);
cout << ".";
cout << ((uClientIPAddress & 0x000000ff) >> 0);
cout << ", port: ";
cout << client[i].uPort << endl;
nIndex++;
}
cout << endl;
}
int mainServer() {
// 1: gethostent
cout << "1: gethostent" << endl;
sethostent(1);
struct hostent * host = NULL;
while ((host = gethostent()) != 0)
{
printhost(host);
cout << endl;
}
endhostent();
// 2: port
int nPort = 0;
cout << "2: please enter ip and port: ";
cin >> nPort;
cout << endl;
// 3: socket
cout << "3: socket" << endl;
int hServer = socket(AF_INET, SOCK_STREAM, 0);
if (hServer == -1) {
cout << "socket error" << endl;
return 1;
} else {
cout << "socket success" << endl;
}
cout << endl;
// 4: setsockopt
cout << "4: setsockopt" << endl;
int yes = 1;
if (setsockopt(hServer, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
cout << "setsockopt error" << endl;
} else {
cout << "setsockopt success" << endl;
}
cout << endl;
// 5: bind
cout << "5: bind" << endl;
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(nPort);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int nBind = bind(hServer, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (nBind == -1) {
cout << "bind error" << endl;
return 1;
} else {
cout << "bind success" << endl;
}
cout << endl;
// 6: listen
cout << "6: listen: ";
if (listen(hServer, MAX_CLIENT_COUNT) == -1) {
cout << "listen error " << endl;
return 1;
} else {
cout << "listen success" << endl;
}
cout << endl;
// client数组
Client_Socket_IPPort hClient[MAX_CLIENT_COUNT] = {0};
for (int i=0; i<MAX_CLIENT_COUNT; i++) {
hClient[i].hSocket = 0;
}
unsigned char cRecv[1024] = {0};
fd_set f;
struct timeval t;
t.tv_sec = 10;
t.tv_usec = 0;
while (1) {
// 将指定的文件描述符集清空
FD_ZERO(&f);
// 将hServer加入f集合
if (!FD_ISSET(hServer, &f))
FD_SET(hServer, &f);
// 将现有client加入f集合
for (int i = 0; i < MAX_CLIENT_COUNT; i++) {
if (hClient[i].hSocket != 0) {
if (!FD_ISSET(hClient[i].hSocket, &f))
FD_SET(hClient[i].hSocket, &f);
}
}
// 最大文件描述符
int nMaxnfds = hServer;
for (int i=0; i<MAX_CLIENT_COUNT; i++) {
if (nMaxnfds < hClient[i].hSocket) {
nMaxnfds = hClient[i].hSocket;
}
}
nMaxnfds++;
// select
int nSelect = select(nMaxnfds, &f, NULL, NULL, &t);
if (nSelect < 0) {
cout << "select error" << endl;
break;
} else if (nSelect == 0) {
}
// new connection
if (FD_ISSET(hServer, &f)) {
cout << "accept client: " << endl;
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
int hAcceptClient = accept(hServer, (struct sockaddr*)&client_addr, &length);
if (hAcceptClient < 0) {
cout << "accept error" << endl;
return 1;
} else {
cout << "accept success" << endl;
}
for (int i=0; i<MAX_CLIENT_COUNT; i++) {
if (hClient[i].hSocket == 0) {
hClient[i].hSocket = hAcceptClient;
hClient[i].uIPAddress = ntohl(client_addr.sin_addr.s_addr);
hClient[i].uPort = ntohs(client_addr.sin_port);
break;
}
}
printclient(hClient);
}
// recv
for (int i=0; i<MAX_CLIENT_COUNT; i++) {
if (hClient[i].hSocket <= 0) {
continue;
}
if (FD_ISSET(hClient[i].hSocket, &f)) {
int nRecvLength = recv(hClient[i].hSocket, cRecv, sizeof(cRecv), 0);
// connect drop
if (nRecvLength <= 0) {
close(hClient[i].hSocket);
FD_CLR(hClient[i].hSocket, &f);
hClient[i].hSocket = 0;
printclient(hClient);
} else {
sockaddr_in recvClient;
recvClient.sin_addr.s_addr = htonl(hClient[i].uIPAddress);
printf("recv from %s:%d", inet_ntoa(recvClient.sin_addr), hClient[i].uPort);
for (int j=0; j<nRecvLength; j++) {
printf(" 0x%02x ", cRecv[j]);
}
cout << endl;
}
}
}
}
// close
cout << "close" << endl;
for (int i=0; i<MAX_CLIENT_COUNT; i++) {
if (hClient[i].hSocket != 0) {
close(hClient[i].hSocket);
}
}
close(hServer);
return 1;
}
int main() {
return mainServer();
}