多路复用I/O可以解决资源限制的问题.着模型实际上是将UDP循环模型用在了TCP上面. 这也就带来了一些问题.如由于服务器依次处理客户的请求,所以可能会导致有的客户 会等待很久.
——————————————————————————————————————————————————————
/*
filename: server.c
function: client input a message and server echo it !
version: ipv4 -> ipv6
conpile: gcc -Wall -lpthread server.c -o server
run: ./server port listennum ipv6
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#define PORT 15636
#define BACKLOG 5
#define MAXLINE 100
typedef struct _CLIENT
{
int fd;
}CLIENT;
int iListenfd;
void *thread(void *v_pArg);
void f(int signo)
{
close(iListenfd);
printf(" --*Server over ! Thank you for use ! *--\n");
exit(0);
}
int main(int argc, char *argv[])
{
if (argc < 4)
printf("usage: server port num ipv6\n"),exit(-1);
signal(SIGINT, f);
fd_set rset, allset;
int maxfd, maxi, i;
CLIENT client[FD_SETSIZE];
unsigned int myport,lisnum;
if (argv[1])
myport = atoi(argv[1]);
else
myport = PORT;
if (argv[2])
lisnum = atoi(argv[2]);
else
lisnum = BACKLOG;
/*create socket*/
//iListenfd = socket(AF_INET, SOCK_STREAM, 0);
iListenfd = socket(AF_INET6, SOCK_STREAM, 0); //ipv6
if (iListenfd < 0) {
perror("socket error"), exit(1);
}
printf("1. creating socket success!\n");
int ireuse = 1;
/*set socket option : reuse addr*/
if (setsockopt(iListenfd, SOL_SOCKET, SO_REUSEADDR,
&ireuse, sizeof(int)) < 0) {
perror("setsockopt error"), exit(1);
}
//struct sockaddr_in serveraddr;
struct sockaddr_in6 serveraddr; //ipv6
bzero((char*)&serveraddr, sizeof(serveraddr));
//serveraddr.sin_family = AF_INET;
serveraddr.sin6_family = AF_INET6; //ipv6
//serveraddr.sin_port = htons(myport);
serveraddr.sin6_port = htons(myport); //ipv6
if (argv[3])
//serveraddr.sin_addr.s_addr = inet_addr(argv[3]);
inet_pton(AF_INET6, argv[3], &serveraddr.sin6_addr);
else
//serveraddr.sin_addr.s_addr = inet_addr(INADDR_ANY);
serveraddr.sin6_addr = in6addr_any; //in6addr_any must little
/*bind socket*/
if (bind(iListenfd, (struct sockaddr *)&serveraddr,
sizeof(serveraddr)) < 0) {
perror("bind error"), exit(1);
}
/* start listening */
if (listen(iListenfd, lisnum) < 0) {
perror("listen error"), exit(1);
} else {
printf("2. Waitting client connect ...\n");
}
maxfd = iListenfd;
maxi = -1;
for (i=0; i < FD_SETSIZE; i++)
{
client[i].fd = -1;
}
FD_ZERO(&allset);
FD_SET(iListenfd, &allset);
pthread_t tid;
//void *ret;
int nready;
int iClientLen, iConnfd, sockfd;
while (1)
{
//struct sockaddr_in clientaddr;
struct sockaddr_in6 clientaddr; //ipv6
rset = allset;
nready = select(maxfd+1, &rset, NULL, NULL, NULL);
printf("3. There are %d fd(s) active.\n", nready);
if (FD_ISSET(iListenfd, &rset)) {
printf("4. Accept ok.\n");
iClientLen = sizeof(clientaddr);
iConnfd = accept(iListenfd, (struct sockaddr *)&clientaddr,
(socklen_t*)&iClientLen);
if (iConnfd < 0) {
perror("accept failed"), exit(1);
} else {
printf("5. Server accepted...\n");
}
for (i=0; i < FD_SETSIZE; i++) {
if (client[i].fd < 0) {
client[i].fd = iConnfd;
break;
}
}
if (i == FD_SETSIZE) {
printf("Too many clients\n");
}
FD_SET(iConnfd, &allset); //add new client fd
if (iConnfd > maxfd)
maxfd = iConnfd; //to sure maxfd is max
if (i > maxi)
maxi = i;
if (--nready <= 0)
continue; //no more new action
}
for (i=0; i <= maxi; i++) {
if ((sockfd = client[i].fd) < 0)
continue;
if (FD_ISSET(sockfd, &rset)) {
pthread_create(&tid, NULL, thread, &sockfd);
FD_CLR(sockfd, &allset);
client[i].fd = -1;
if (--nready <= 0)
break;
}
}
}
close(iListenfd);
return EXIT_SUCCESS;
}
void *thread(void *v_pArg)
{
int iConnfd = *((int *)v_pArg);
int idata;
char temp[100];
printf("\n-----------------------start----------------------------\n");
while (1) {
idata = recv(iConnfd, temp, 100, 0);
if (idata > 0)
{
printf("client say: %s\n", temp);
}
send(iConnfd, temp, 100, 0);
if (strcmp(temp,"bye\n") == 0)
{
printf("-----------------------end----------------------------\n");
close(iConnfd);
break;
}
}
return NULL;
}
/*
filename: clent.c
function: client input a message and server echo it !
version: ipv4 -> ipv6
conpile: gcc -Wall -lpthread client.c -o client
run: ./client ipv6 port
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <pthread.h>
#define MAXLINE 100
#define PORT 15636
void *threadsend(void *v_parg);
void *threadrecv(void *v_parg);
int main(int argc, char *argv[])
{
if (argc < 3)
printf("usage: client ipv6 port\n"),exit(-1);
int iclientfd;
unsigned int myport;
if (argv[2])
myport = atoi(argv[2]);
else
myport = PORT;
/* create socket */
//iclientfd = socket(AF_INET, SOCK_STREAM, 0);
iclientfd = socket(AF_INET6, SOCK_STREAM, 0); //ipv6
if (iclientfd < 0) {
perror("socket error"), exit(1);
}
//struct sockaddr_in serveraddr;
struct sockaddr_in6 serveraddr; //ipv6
bzero((char*)&serveraddr, sizeof(serveraddr));
//serveraddr.sin_family = AF_INET;
serveraddr.sin6_family = AF_INET6; //ipv6
//serveraddr.sin_port = htons(myport);
serveraddr.sin6_port = htons(myport); //ipv6
if (argv[1])
//serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
inet_pton(AF_INET6, argv[1], &serveraddr.sin6_addr); //ipv6
else
//serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
inet_pton(AF_INET6, "::1/128", &serveraddr.sin6_addr);
/* try connect */
if (connect(iclientfd, (struct sockaddr *)&serveraddr,
sizeof(serveraddr)) < 0) {
perror("connect error\n"), exit(1);
} else {
printf("Client connected...\n");
}
pthread_t tid;
pthread_create(&tid, NULL, threadsend, &iclientfd);
pthread_join(tid, 0);
return EXIT_SUCCESS;
}
void *threadsend(void *v_parg)
{
int iconnfd = *((int*)v_parg);
char sendbuf[100], recvbuf[100];
int idata;
printf("\n-----------------------start----------------------------\n");
while (1)
{
fgets(sendbuf, 100, stdin);
send(iconnfd, sendbuf, 100, 0);
printf(" ~client send OK! ^-^\n");
idata = recv(iconnfd, recvbuf, 100, 0);
if (idata > 0) {
printf("server echo: %s\n", recvbuf);
}
if (strcmp(sendbuf, "bye\n") == 0) {
printf("-----------------------end----------------------------\n");
printf(" --* Client over ! Thank you for use! *--\n");
close(iconnfd);
break;
}
}
return NULL;
}
——————————————————————————————————————————————————————