/*
* name: net_slct.c CEP: Communication End-Point
* written by saodrin zhang for test
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define UINT16 unsigned short int
#ifndef INPORT_ANY
#define INPORT_ANY 0
#endif
#define SVC_PORT 9999
typedef struct NET_INFO_T
{
int fd;
unsigned long inet_peer_addr;
UINT16 inet_peer_port;
}NET_INFO;
int main_serv(int argc, char *argv[]);
int main_clnt(int argc, char *argv[]);
int main(int argc, char *argv[])
{
int ret;
if (argc == 1)
ret = main_serv(argc, argv);
else
ret = main_clnt(argc, argv);
return ret;
}
#define MAX_CNCT_NUM 8
#define BUF_SIZE 256
int main_serv(int argc, char *argv[])
{
int ret, i, k, n;
int len;
int inp_fd, sockfd, cnctfd, sfd, dgrmfd, maxfd;
int num, entry; /* clntfd[], clntnum */
struct NET_INFO_T netinfo[MAX_CNCT_NUM];
int opts, sndFlag;
fd_set readfds, writefds;
struct sockaddr_in bindaddr; //servaddr
struct sockaddr_in cnctaddr; //clntaddr
struct sockaddr_in intfaddr;
struct timeval timeout;
char text[BUF_SIZE], buf[BUF_SIZE];
char sBuf[MAX_CNCT_NUM][BUF_SIZE];
maxfd = 0;
/*inp_fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);*/
inp_fd = fileno(stdin);
printf("Inp_fd is %d\n", inp_fd); /* assert(inp_fd >= 0); */
fcntl(inp_fd, F_SETFL, fcntl(inp_fd, F_GETFL) | O_NONBLOCK);
/* create TCP socket, assign the Protocol Family for communication */
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
printf("TCP: socket create error!\n");
return -1;
}
memset(&bindaddr, 0, sizeof(struct sockaddr_in));
/* AF_INET: Address Family */
bindaddr.sin_family = AF_INET;
/* INADDR_ANY: address of any interface owned by the host */
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindaddr.sin_port = htons(SVC_PORT);
bzero(&(bindaddr.sin_zero), 8); /* */
/* 将用于监听的插接口sockfd设置为地址重用方式 */
opts = 1; /* option enable */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &opts, sizeof(opts)) < 0)
{
close(sockfd);
printf("TCP: setsockopt error!\n");
return -1;
}
if (bind(sockfd, (struct sockaddr *)&bindaddr, sizeof(struct sockaddr_in)) < 0)
{
printf("TCP: bind error!\n");
return -1;
}
/* create UDP socket */
if ((sfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
{
printf("UDP: socket create error!\n");
return -1;
}
memset(&bindaddr, 0, sizeof(struct sockaddr_in));
/* AF_INET: Address Family */
bindaddr.sin_family = AF_INET;
/* INADDR_ANY: address of any interface owned by the host */
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindaddr.sin_port = htons(SVC_PORT);
bzero(&(bindaddr.sin_zero), 8); /* */
/* 置 socket 为地址重用方式 */
opts = 1; /* option enable */
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *) &opts, sizeof(opts)) < 0)
{
close(sfd);
printf("UDP setsockopt error!\n");
return -1;
}
if (bind(sfd, (struct sockaddr *)&bindaddr, sizeof(struct sockaddr_in)) < 0)
{
printf("UDP: bind error!\n");
return -1;
}
for (i = 0; i < MAX_CNCT_NUM; i++)
{
netinfo[i].fd = -1; /* -1 indicates available entry for client fd */
}
listen(sockfd, 5);
entry = 0;
num = 0;
if (inp_fd >= 0)
{
fcntl(inp_fd, F_SETFL, O_NONBLOCK);
}
if (sockfd >= 0)
{
fcntl(sockfd, F_SETFL, O_NONBLOCK);
}
if (sfd >= 0)
{
fcntl(sfd, F_SETFL, O_NONBLOCK);
}
text[0] = '\0';
for (i = 0; i < MAX_CNCT_NUM; i++) sBuf[i][0] = '\0';
sndFlag = 0;
while (1) /* 轮循、并发或(多路)复用 */
{
timeout.tv_sec = 1;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(inp_fd, &readfds);
maxfd = inp_fd;
if (sockfd >= 0)
{
FD_SET(sockfd, &readfds);
maxfd = sockfd > maxfd ? sockfd : maxfd;
}
if (sfd >= 0)
{
FD_SET(sfd, &readfds);
maxfd = sfd > maxfd ? sfd : maxfd;
}
for (i = 0, n = 0; i < MAX_CNCT_NUM && n < num; i++)
{
if (netinfo[i].fd > 0)
{
FD_SET(netinfo[i].fd, &readfds);
if (sBuf[i][0] != '\0')
{
/* printf("WR: FD_SET...\n"); */
FD_SET(netinfo[i].fd, &writefds);
}
maxfd = netinfo[i].fd > maxfd ? netinfo[i].fd : maxfd;
n++;
}
}
ret = select(maxfd+1, &readfds, &writefds, NULL, &timeout);
//select error when ret = -1
if (ret == -1) printf("select error!\n");
//time out when ret = 0
//if (ret == 0) printf("select time out.\n");
//data coming when ret>0
if (ret > 0)
{
/* printf("----------------\n"); */
if (FD_ISSET(inp_fd, &readfds))
{
/*i = read(inp_fd, &ch, 1);
if('\n' == ch) continue;
else printf("Input is %c\n", ch);*/
n = read(inp_fd, buf, BUF_SIZE);
if (n >= 0)
{
i = 0;
k = 0;
while (i < n && isspace(buf[i])) i++;
while (i < n && !isspace(buf[i]))
{
buf[k] = buf[i];
k++;
i++;
}
i = k < BUF_SIZE ? k : BUF_SIZE-1;
buf[i] = '\0';
if (i > 0) strcpy(text, buf);
}
else
{
printf("RD STDIN error!\n");
break;
}
if ('\0' == buf[0]) continue;
else printf("Inputed: %s\n", text);
if ('q' == text[0])
{
/* close all I/O descriptors and quit */
break;
}
}
if (FD_ISSET(sockfd, &readfds))
{
len = sizeof(struct sockaddr_in);
cnctfd = accept(sockfd, (struct sockaddr *)&cnctaddr, (socklen_t *)&len);
if (cnctfd < 0)
{
if (cnctfd != EWOULDBLOCK && \
cnctfd != ECONNABORTED && \
cnctfd != EINTR)
{
shutdown(sockfd, SHUT_RDWR);
sockfd = -1; /* error fd */
close(sockfd);
}
}
else
{
len = sizeof(struct sockaddr_in);
getsockname(cnctfd, (struct sockaddr *)&intfaddr, (socklen_t *)&len);
printf("=>: Connection from %s:%d on %s:%d\n", \
inet_ntoa(cnctaddr.sin_addr), ntohs(cnctaddr.sin_port), \
inet_ntoa(intfaddr.sin_addr), ntohs(intfaddr.sin_port));
if (num == MAX_CNCT_NUM)
{
shutdown(cnctfd, SHUT_RDWR);
close(cnctfd);
}
else
{
fcntl(cnctfd, F_SETFL, O_NONBLOCK);
netinfo[entry].fd = cnctfd; /* client fd */
netinfo[entry].inet_peer_addr = cnctaddr.sin_addr.s_addr;
netinfo[entry].inet_peer_port = cnctaddr.sin_port;
for (i = 0; i < MAX_CNCT_NUM; i++)
{
if (netinfo[i].fd < 0)
{
entry = i;
break;
}
}
/* assert(i < MAX_CNCT_NUM); */
printf("Accept TCP fd = %d\n", cnctfd);
num++;
} /* end if (num == MAX_CNCT_NUM) else */
} /* end if (cnctfd < 0) else */
} /* end if (FD_ISSET(sockfd, &readfds)) */
if (FD_ISSET(sfd, &readfds))
{
len = sizeof(struct sockaddr_in);
n = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *)&cnctaddr, (socklen_t *)&len);
if (n > 0)
{
len = sizeof(struct sockaddr_in);
getsockname(cnctfd, (struct sockaddr *)&intfaddr, (socklen_t *)&len);
printf("->: Datagraph from %s:%d on %s:%d\n", \
inet_ntoa(cnctaddr.sin_addr), ntohs(cnctaddr.sin_port), \
inet_ntoa(intfaddr.sin_addr), ntohs(intfaddr.sin_port));
buf[n] = '\0';
for (i = 0, k = 0; i < MAX_CNCT_NUM && k < num; i++)
{
if (netinfo[i].fd >= 0)
{
if (netinfo[i].inet_peer_addr == cnctaddr.sin_addr.s_addr && \
netinfo[i].inet_peer_port == cnctaddr.sin_port)
{
len = sizeof(int);
if (getsockopt(netinfo[i].fd, SOL_SOCKET, SO_TYPE, (char *)&opts, (socklen_t *)&len) == 0 && \
opts == SOCK_DGRAM)
break;
}
k++;
}
}
/* printf("DEBUG: i = %d, k = %d, num = %d\n", i, k, num); */
if (i >= MAX_CNCT_NUM || k >= num) /* not found */
{
if (num >= MAX_CNCT_NUM) /* no more resource */
{
printf("UDP discard: %s", buf);
}
else
{
/* create UDP socket and set it's endpoint */
dgrmfd = socket(PF_INET, SOCK_DGRAM, 0);
memset(&bindaddr, 0, sizeof(struct sockaddr_in));
bindaddr.sin_family = AF_INET;
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* better to use the address that data arrived.
Ref to IP_RECVDSTADDR */
bindaddr.sin_port = htons(SVC_PORT);
bzero(&(bindaddr.sin_zero), 8);
opts = 1; /* option enable */
setsockopt(dgrmfd, SOL_SOCKET, SO_REUSEADDR, (char *) &opts, sizeof(opts));
/* 在允许使用完全重复的 cep 对 udp socket 进行绑定的系统中,两侧的 cep 都匹配的 socket 会被优先选用来进行通讯 */
bind(dgrmfd, (struct sockaddr *)&bindaddr, sizeof(struct sockaddr_in));
len = sizeof(struct sockaddr_in);
connect(dgrmfd, (struct sockaddr *)&cnctaddr, len);
/* add the cnctfd to the CEP array */
fcntl(dgrmfd, F_SETFL, O_NONBLOCK);
/* assert(entry < MAX_CNCT_NUM); */
netinfo[entry].fd = dgrmfd; /* client fd */
netinfo[entry].inet_peer_addr = cnctaddr.sin_addr.s_addr;
netinfo[entry].inet_peer_port = cnctaddr.sin_port;
/* use the supplied fd to communicate later */
printf("Supply UDP fd = %d\n", dgrmfd);
if (buf[0] != '\0' && text[0] != '\0')
{
sprintf(sBuf[entry], "%s + ", text);
strcat(sBuf[entry], buf);
}
for (i = 0; i < MAX_CNCT_NUM; i++)
{
if (netinfo[i].fd < 0)
{
entry = i;
break;
}
}
/* assert(i < MAX_CNCT_NUM); */
num++;
} /* end if (num >= MAX_CNCT_NUM) else */
}
else
{
/* printf("UDP socket found: %d\n", netinfo[i].fd); */
if (buf[0] != '\0' && text[0] != '\0')
{
sprintf(sBuf[i], "%s + ", text);
strcat(sBuf[i], buf);
}
} /* end if (i >= MAX_CNCT_NUM || k >= num) else */
}
else if (n == 0)
{
printf("UDP RD: peer is closed!\n");
for (i = 0, k = 0; i < MAX_CNCT_NUM && k < num; i++)
{
if (netinfo[i].fd >= 0 && netinfo[i].inet_peer_addr == cnctaddr.sin_addr.s_addr)
{
shutdown(netinfo[i].fd, SHUT_RDWR);
close(netinfo[i].fd);
netinfo[i].fd = -1;
entry = i < entry ? i : entry;
num--;
}
}
}
else
{
shutdown(sfd, SHUT_RDWR);
close(sfd);
sfd = -1;
} /* end else if (n == 0) else */
//k = sendto(sfd, buf, n, 0, (struct sockaddr *)&cnctaddr, sizeof(struct sockaddr));
} /* end if (FD_ISSET(sfd, &readfds)) */
for (i = 0, k = 0; i < MAX_CNCT_NUM && k < num; i++)
{
if (netinfo[i].fd > 0 && FD_ISSET(netinfo[i].fd, &readfds))
{
n = read(netinfo[i].fd, buf, BUF_SIZE);
if (n > 0)
{
buf[n] = '\0';
printf("RD sockfd[%d]: %s", i, buf);
if (buf[0] != '\0' && text[0] != '\0')
{
sprintf(sBuf[i], "%s + ", text);
strcat(sBuf[i], buf);
}
k++;
}
else if (n == 0)
{
printf("RD sockfd[%d]: peer is closed.\n", i);
shutdown(netinfo[i].fd, SHUT_RDWR);
close(netinfo[i].fd);
sBuf[i][0] = '\0';
netinfo[i].fd = -1;
entry = i < entry ? i : entry;
num--;
}
else
{
switch (errno)
{
case EAGAIN:
#if EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
k++;
break;
case EINTR:
/* we were stopped _before_ we had a connection */
case ECONNABORTED: /* this is a FreeBSD thingy */
/* we were stopped _after_ we had a connection */
k++;
break;
case EMFILE: /* out of fds */
k++;
break;
default:
perror("readxxxx");
printf("errno %d: i = %d, k = %d, sockfd = %d\n", errno, i, k, netinfo[i].fd);
shutdown(netinfo[i].fd, SHUT_RDWR);
close(netinfo[i].fd);
netinfo[i].fd = -1; /* close it */
entry = i < entry ? i : entry;
num--;
break;
} /* end switch (errno) */
} /* end if (n > 0) */
} /* end if (netinfo[i].fd > 0 && FD_ISSET(netinfo[i].fd, &readfds) */
} /* end for (...; i < MAX_CNCT_NUM && k < num; ...) */
for (i = 0, k = 0; i < MAX_CNCT_NUM && k < num; i++)
{
if (netinfo[i].fd > 0 && FD_ISSET(netinfo[i].fd, &writefds))
{
len = strlen(sBuf[i]);
n = write(netinfo[i].fd, sBuf[i], len);
if (n > 0) /* assert(n == len); */
{
printf("WR sockfd[%d]: %s", i, sBuf[i]);
sBuf[i][0] = '\0';
k++;
}
else if (n == 0)
{
printf("WR sockfd[%d]: peer is closed.", i);
shutdown(netinfo[i].fd, SHUT_RDWR);
close(netinfo[i].fd);
sBuf[i][0] = '\0';
netinfo[i].fd = -1;
entry = i < entry ? i : entry;
num--;
}
else /* error */
{
switch (errno)
{
case EAGAIN:
#if EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
k++;
break;
case EINTR:
/* we were stopped _before_ we had a connection */
case ECONNABORTED: /* this is a FreeBSD thingy */
/* we were stopped _after_ we had a connection */
k++;
break;
case EMFILE: /* out of fds */
k++;
break;
default:
perror("write");
shutdown(netinfo[i].fd, SHUT_RDWR);
close(netinfo[i].fd);
netinfo[i].fd = -1; /* close it */
entry = i < entry ? i : entry;
num--;
break;
} /* end switch (errno) */
} /* end if (n > 0) */
} /* end if (netinfo[i].fd > 0 && FD_ISSET(netinfo[i].fd, &readfds)) */
} /* end for (...; i < MAX_CNCT_NUM && k < num; ...) */
} /* end if (ret > 0) */
}
return 0;
}
int main_clnt(int argc, char *argv[])
{
int ret, i, n;
int len;
int inp_fd, sockfd, sfd, cofd, dgfd, maxfd;
int opts, sndFlag;
fd_set readfds, writefds;
struct sockaddr_in bindaddr; //local client address
struct sockaddr_in cnctaddr; //remote server address
struct sockaddr_in intfaddr;
char intfname[16];
struct timeval timeout;
struct hostent *host;
struct in_addr servAddr;
unsigned long servIP;
char text[BUF_SIZE], buf[BUF_SIZE];
if (argc < 2)
{
return -1;
}
host = gethostbyname(argv[1]); /* name is an ASCII or digital notation */
if (host != NULL)
{
memcpy(&servAddr, host->h_addr_list[0], sizeof(struct in_addr));
servIP = ntohl(servAddr.s_addr);
printf("destIP = 0x%x\n", servIP);
}
else
{
printf("Error: gethostbyname\n");
return -1;
}
/*inp_fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);*/
inp_fd = fileno(stdin);
printf("Inp_fd is %d\n", inp_fd); /* assert(inp_fd >= 0); */
fcntl(inp_fd, F_SETFL, fcntl(inp_fd, F_GETFL) | O_NONBLOCK);
maxfd = inp_fd;
/* create TCP socket, assign the Protocol Family for communication */
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
printf("TCP: socket create error!\n");
return -1;
}
memset(&bindaddr, 0, sizeof(struct sockaddr_in));
/* AF_INET: Address Family */
bindaddr.sin_family = AF_INET;
/* INADDR_ANY: address of any interface owned by the host */
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindaddr.sin_port = htons(0); /* use SVC_PORT to enable only one client per home */
bzero(&(bindaddr.sin_zero), 8); /* */
/* 置 socket 重新使用 */
opts = 1; /* option enable */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &opts, sizeof(opts)) < 0)
{
close(sockfd);
printf("setsockopt error!\n");
return -1;
}
if (SVC_PORT == ntohs(bindaddr.sin_port))
{
if ((n = bind(sockfd, (struct sockaddr *)&bindaddr, sizeof(struct sockaddr_in))) == -1)
{
printf("TCP: Default CEP is already used...\n");
/* mask the following code to enable only one client instance */
bindaddr.sin_port = htons(0); /* INPORT_ANY */
n = bind(sockfd, (struct sockaddr *)&bindaddr, sizeof(struct sockaddr_in));
}
}
else
{
n = bind(sockfd, (struct sockaddr *)&bindaddr, sizeof(struct sockaddr_in));
}
if (n == -1)
{
printf("TCP bind error!\n");
return -1;
}
else
{
len = sizeof(struct sockaddr_in);
/* getsockname() is used to get the locally-bound endpoint on a bind()'d, connect()'d
* or accept()'d socket. If the socket is bind()'d with INADDR_ANY and not connect()'d,
* the address value is unspecified.
* see also: getpeername()
*/
if (0 == getsockname(sockfd, (struct sockaddr *)&intfaddr, (socklen_t *)&len))
{
printf("TCP bind on port %d\n", ntohs(intfaddr.sin_port));
}
else
{
printf("TCP bind on unknown port.\n");
}
}
memset(&cnctaddr, 0, sizeof(struct sockaddr_in));
/* AF_INET: Address Family */
cnctaddr.sin_family = AF_INET;
/* host address to connect */
cnctaddr.sin_addr.s_addr = htonl(servIP);
cnctaddr.sin_port = htons(SVC_PORT);
bzero(&(cnctaddr.sin_zero), 8); /* */
if (connect(sockfd, (struct sockaddr *)&cnctaddr, sizeof(struct sockaddr_in)) == -1)
{
/* if (errno == EADDRINUSE) ...*/
perror("TCP connect");
return -1;
}
else
{
len = sizeof(struct sockaddr_in);
if (0 == getsockname(sockfd, (struct sockaddr *)&intfaddr, (socklen_t *)&len))
{
inet_ntop(AF_INET, &intfaddr.sin_addr, intfname, 16);
printf("TCP Connect to %s:%d on interface %s with port %d\n", \
inet_ntoa(cnctaddr.sin_addr), ntohs(cnctaddr.sin_port), \
intfname, ntohs(intfaddr.sin_port));
}
cofd = sockfd;
}
/* create UDP socket */
if ((sfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
{
printf("UDP: socket create error!\n");
return -1;
}
memset(&bindaddr, 0, sizeof(struct sockaddr_in));
/* AF_INET: Address Family */
bindaddr.sin_family = AF_INET;
/* INADDR_ANY: address of any interface owned by the host */
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindaddr.sin_port = htons(SVC_PORT);
bzero(&(bindaddr.sin_zero), 8); /* */
/* sfd为UDP插接口,不要设置成地址重用方式;否则当多个插接口使用相同的cep进行 */
/* 通讯时(绑定和连接返回正常),不能正常收发数据 */
/* (对TCP插接口,当使用相同的cep绑定时,即使设置成地址重用方式也会返回错误) */
//opts = 1; /* option enable */
//if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *) &opts, sizeof(opts)) < 0)
//{
// close(sfd);
// printf("setsockopt error!\n");
// return -1;
//}
if (bind(sfd, (struct sockaddr *)&bindaddr, sizeof(struct sockaddr_in)) == -1)
{
printf("UDP: Default CEP is already used...\n");
bindaddr.sin_port = htons(0); /* INPORT_ANY */
if (bind(sfd, (struct sockaddr *)&bindaddr, sizeof(struct sockaddr_in)) == -1)
{
printf("UDP bind error!\n");
return -1;
}
else
{
len = sizeof(struct sockaddr_in);
if (0 == getsockname(sfd, (struct sockaddr *)&intfaddr, (socklen_t *)&len))
{
printf("UDP bind on port %d\n", ntohs(intfaddr.sin_port));
}
else
{
printf("UDP bind on unknown port.\n");
}
}
}
else
{
printf("UDP Bind on Default CEP port %d.\n", ntohs(bindaddr.sin_port));
}
memset(&cnctaddr, 0, sizeof(struct sockaddr_in));
/* AF_INET: Address Family */
cnctaddr.sin_family = AF_INET;
/* host address to connect */
cnctaddr.sin_addr.s_addr = htonl(servIP);
cnctaddr.sin_port = htons(SVC_PORT);
bzero(&(cnctaddr.sin_zero), 8); /* */
if (connect(sfd, (struct sockaddr *)&cnctaddr, sizeof(struct sockaddr_in)) == -1)
{
/* if (errno == EADDRINUSE) ...*/
perror("UDP connect");
return -1;
}
else
{
len = sizeof(struct sockaddr_in);
if (0 == getsockname(sfd, (struct sockaddr *)&intfaddr, (socklen_t *)&len))
{
inet_ntop(AF_INET, &intfaddr.sin_addr, intfname, 16);
printf("UDP Connect to %s:%d on interface %s with port %d\n", \
inet_ntoa(cnctaddr.sin_addr), ntohs(cnctaddr.sin_port), \
intfname, ntohs(intfaddr.sin_port));
}
dgfd = sfd;
}
text[0] = '\0';
sndFlag = 0;
maxfd = dgfd > cofd ? dgfd : cofd;
while (1)
{
timeout.tv_sec = 1;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(inp_fd, &readfds);
if (cofd > 0)
{
FD_SET(cofd, &readfds);
maxfd = cofd > maxfd ? cofd : maxfd;
}
if (dgfd > 0)
{
FD_SET(dgfd, &readfds);
maxfd = dgfd > maxfd ? dgfd : maxfd;
}
if (sndFlag != 0)
{
FD_SET(cofd, &writefds);
FD_SET(dgfd, &writefds);
}
ret = select(maxfd+1, &readfds, &writefds, NULL, &timeout);
//select error when ret = -1
if (ret == -1) printf("select error\n");
//time out when ret = 0
//if (ret == 0) printf("select time out\n");
//data coming when ret>0
if (ret > 0)
{
if (FD_ISSET(inp_fd, &readfds))
{
/*i = read(inp_fd, &ch, 1);
if('\n' == ch) continue;
else printf("Input is %c\n", ch);*/
n = read(inp_fd, text, BUF_SIZE);
if (n >= 0)
{
text[n] = '\0';
}
else
{
printf("RD STDIN error!\n");
text[0] = '\0';
}
if ('\n' == text[0]) continue;
else printf("Inputed: %s", text);
if ('q' == text[0]) break;
else sndFlag = 1;
}
if (FD_ISSET(cofd, &readfds))
{
n = recv(cofd, buf, BUF_SIZE, MSG_DONTROUTE);
if (n > 0)
{
buf[n] = '\0';
printf("TCP Recv OK: %s", buf);
}
else if (n == 0) /* peer is closed */
{
printf("TCP: Peer is closed ...\n");
shutdown(cofd, SHUT_RDWR);
close(cofd);
break;
}
else
{
printf("TCP Recv error!\n");
}
}
if (FD_ISSET(cofd, &writefds))
{
if ((n = strlen(text)) > 0)
{
if ((i = send(cofd, text, n, MSG_DONTROUTE)) != n)
{
printf("TCP: Try to send again...\n");
sndFlag = 1;
}
else
{
printf("TCP Send OK: %s", text);
sndFlag = 0;
}
}
else
{
sndFlag = 0; /* FD_CLR(cofd, &writefds); */
printf("TCP: Nothing to be sent\n");
if ((i = write(cofd, "...\n", 4)) != 4)
perror("Test write");
} /* end if ((n = strlen(text)) > 0) */
} /* end if (FD_ISSET(cofd, &writefds)) */
if (FD_ISSET(dgfd, &readfds))
{
n = recv(dgfd, buf, BUF_SIZE, MSG_DONTROUTE);
if (n > 0)
{
buf[n] = '\0';
printf("UDP Recv OK: %s", buf);
}
else if (n == 0) /* peer is closed */
{
printf("UDP: Peer is closed ...\n");
shutdown(dgfd, SHUT_RDWR);
close(dgfd);
break;
}
else
{
printf("UDP Recv error!\n");
}
}
if (FD_ISSET(dgfd, &writefds))
{
if ((n = strlen(text)) > 0)
{
if ((i = send(dgfd, text, n, MSG_DONTROUTE)) != n)
{
printf("UDP: Try to send again...\n");
sndFlag = 1;
}
else
{
printf("UDP Send OK: %s", text);
sndFlag = 0;
}
}
else
{
sndFlag = 0; /* FD_CLR(cofd, &writefds); */
printf("UDP: Nothing to be sent\n");
if ((i = write(cofd, "...\n", 4)) != 4)
perror("Test write");
} /* end if ((n = strlen(text)) > 0) */
} /* end if (FD_ISSET(dgfd, &writefds)) */
} /* end if (ret > 0) */
} /* end while (1) */
return ret;
}
/* ------------------------------------------------------------------- */
#if 0
/*
* recvfromto Like recvfrom, but also stores the destination
* IP address. Useful on multihomed hosts.
*
* Should work on Linux and BSD.
*
* Copyright (C) 2002 Miquel van Smoorenburg.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*/
#include
#include
#include
#include
#include
#include
#include
/* Remove this when autoconf can detect this. */
#if defined(IP_PKTINFO) && !defined(HAVE_IP_PKTINFO)
# define HAVE_IP_PKTINFO 1
#elif defined(IP_RECVDSTADDR) && !defined(HAVE_IP_RECVDSTADDR)
# define HAVE_IP_RECVDSTADDR
#endif
int recvfromto(int s, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen,
struct sockaddr *to, socklen_t *tolen)
{
struct msghdr msgh;
struct cmsghdr *cmsg;
struct iovec iov;
char cbuf[1024];
int opt, err;
/*
* If from or to are set, they must be big enough
* to store a struct sockaddr_in.
*/
if ((from && (!fromlen || *fromlen < sizeof(struct sockaddr_in))) ||
(to && (!tolen || *tolen < sizeof(struct sockaddr_in))))
{
errno = EINVAL;
return -1;
}
if (tolen) *tolen = 0;
#ifdef HAVE_IP_PKTINFO
/*
* IP_PKTINFO doesn't provide sin_port so we have to
* retrieve it using getsockname().
*/
if (to)
{
struct sockaddr_in si;
socklen_t l = sizeof(si);
((struct sockaddr_in *)to)->sin_family = AF_INET;
((struct sockaddr_in *)to)->sin_port = 0;
l = sizeof(si);
if (getsockname(s, (struct sockaddr *)&si, &l) == 0)
{
((struct sockaddr_in *)to)->sin_port = si.sin_port;
((struct sockaddr_in *)to)->sin_addr = si.sin_addr;
}
*tolen = sizeof(struct sockaddr_in);
}
#endif
/* Set MSG_DONTWAIT if O_NONBLOCK was set. */
if (fcntl(s, F_GETFL) & O_NONBLOCK) flags |= MSG_DONTWAIT;
/* Set up iov and msgh structures. */
iov.iov_base = buf;
iov.iov_len = len;
msgh.msg_control = cbuf;
msgh.msg_controllen = sizeof(cbuf);
msgh.msg_name = from;
msgh.msg_namelen = fromlen ? *fromlen : 0;
msgh.msg_iov = &iov;
msgh.msg_iovlen = 1;
#ifdef HAVE_IP_PKTINFO
/* Set the IP_PKTINFO option (Linux). */
opt = 1;
setsockopt(s, SOL_IP, IP_PKTINFO, &opt, sizeof(opt));
#endif
#ifdef HAVE_IP_RECVDSTADDR
/* Set the IP_RECVDSTADDR option (BSD). */
opt = 1;
setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt));
#endif
/* Receive one packet. */
err = recvmsg(s, &msgh, flags);
if (fromlen) *fromlen = msgh.msg_namelen;
/* Process auxiliary received data in msgh */
for (cmsg = CMSG_FIRSTHDR(&msgh);
cmsg != NULL && cmsg->cmsg_len >= sizeof(*cmsg);
cmsg = CMSG_NXTHDR(&msgh,cmsg))
{
#ifdef HAVE_IP_PKTINFO
if (cmsg->cmsg_level == SOL_IP
&& cmsg->cmsg_type == IP_PKTINFO)
{
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
if (to)
{
((struct sockaddr_in *)to)->sin_addr = i->ipi_addr;
*tolen = sizeof(struct sockaddr_in);
}
break;
}
#endif
#ifdef HAVE_IP_RECVDSTADDR
if (cmsg->cmsg_level == IPPROTO_IP
&& cmsg->cmsg_type == IP_RECVDSTADDR)
{
struct in_addr *i = (struct in_addr *)CMSG_DATA(cmsg);
if (to)
{
((struct sockaddr_in *)to)->sin_addr = *i;
*tolen = sizeof(struct sockaddr_in);
}
}
#endif
}
return err;
}
#ifdef STANDALONE
#include
#include
#include
#include
/*
* Small test program to test recvfromto
*/
int main(int argc, char **argv)
{
struct sockaddr_in from, to, in;
char buf[1024];
int port = 20000;
int n, s, fl, tl;
if (argc > 1) port = atoi(argv[1]);
s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
in.sin_family = AF_INET;
in.sin_port = htons(port);
in.sin_addr.s_addr = INADDR_ANY;
bind(s, (struct sockaddr *)&in, sizeof(in));
while (1)
{
fl = tl = sizeof(struct sockaddr_in);
memset(&from, 0, sizeof(from));
memset(&to, 0, sizeof(to));
if ((n = recvfromto(s, buf, sizeof(buf), 0,
(struct sockaddr *)&from, &fl,
(struct sockaddr *)&to, &tl)) < 0)
{
perror("recvfromto");
break;
}
printf("Received a packet of %d bytes\n", n);
printf(" src ip:port %s:%d\n",
inet_ntoa(from.sin_addr), ntohs(from.sin_port));
printf(" dst ip:port %s:%d\n",
inet_ntoa(to.sin_addr), ntohs(to.sin_port));
}
return 0;
}
#endif /* STANDALON */
/* end */
#endif
阅读(1484) | 评论(0) | 转发(0) |