一.unix 规划下关于select 模式(服务器端)
1.建立socket套接字
int nsock = socket(AF_UNIX,SOCK_STREAM,0);
2.设置socket缓冲大小.
setsockopt(nsock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr));
3.bind 服务器的地址到套接字
bind(nsock,(struct sockaddr *)&name,len);
4.建立侦听,此可以设置连接数
listen(nsock,5);
5.建立侦听线程,线程中调用accept等待客户端的连接
accept(nSock, (struct sockaddr *) &name, &len))
6.在线程中将套接字描述符及连接描述符加入FD_SET集中
int nSock; //为套接字描述符
fd_set fd_socks;//为FD集 异步I/O模型
int nconnectlist[MAX_CON];//连接描述符
unsigned int nMax_Sock ;//最大的描述符
void Build_Select()
{
FD_ZERO(&fd_socks);
FD_SET(nsock,&fd_socks);
for(int i =0;i<MAX_CON;i++)
{
if(nconnectlist[i] != 0)
FD_SET(nconnectlist[i],&fd_socks);
if(nconnectlist[i]>nMax_Sock)
nMax_Sock = nconnectlist[i];
}
}
在线程内结构如下:
while(TRUE)
{
int nReadCount = select(nMax_Sock+1, &nsocks, (fd_set *) 0,
(fd_set *) 0, &timeout);
//select 有三个fd集,读,写,其它
if(nReadCount<0)
{
printf("Select error/n");//select错误
}
else if (0=nReadCount)
{
printf("none/n");//没有可读数据
}
else
{
printf("read data");//有可读数据
ReadSocket();//读数据函数
}
}
void ReadSocket()
{
if(FD_ISSET(nsock,&fd_socks);
{
//新客户端连接
}
for(int i =0;i<MAX_CON;i++)
{
if(FD_ISSET(nconnectlist[i],&fd_socks)
{
//读客户数据
}
}
}
7.关闭连接及套接字
for(int i =0;i<nconnectlist[i];i++)
{
if(nconnectlist[i]>0)
close(nconnectlist[i]);
}
close(nsock);
二.unix 规划下关于select 模式(客户端)
1.建立socket套接字
int nsock = socket(AF_UNIX,SOCK_STREAM,0);
2.设置socket缓冲大小.
setsockopt(nsock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr));
3.连接服务器端
connect(nsock, (struct sockaddr *) &name, len);
4.建连接线程
fd_set fd_socks;//为FD集 异步I/O模型
int nconnectlist[MAX_CON];//连接描述符
unsigned int nMax_Sock ;//最大的描述符
nMax_Sock = nSock+1;
while(TRUE)
{
FD_ZERO(&fd_socks);
FD_SET(&nMax_Sock,&fd_socks);
FD_SET(0,&fd_socks);
int nReadCount = select(nMax_Sock+1, &nsocks, (fd_set *) 0,
(fd_set *) 0, &timeout);
//select 有三个fd集,读,写,其它
if(FD_ISSET(nsock,&fd_socks))
{
int readcount = recv(nsock,buf,len);//接收数据
if(readcount<1)
{
close(nSock);//关闭连接
exit(0);
}
write(1,buf,len);//向控制台写读入数据
}
if(FD_ISSET(0,&fd_set)
{
int readcount = read(0,buf,len);
//读取标准输入 0为输入stdin,1为输出stdout,2错误stderr
if(readcount <1)
{
close(nsock);
exit(0);
}
send(nsock,buf,len);//发送数据
}
}
5.关闭连接及套接字
close(nsock);
附:服务器程序
#include "sockhelp.h"
#include <ctype.h>
#include <sys/time.h>
#include <fcntl.h>
int sock;
/* The socket file descriptor for our "listening"socket */
int connectlist[5]; /* Array of connected sockets so we know who we are talking to */
fd_set socks; /* Socket file descriptors we want to wake up for, using select() */
int highsock; /* Highest #'d file descriptor, needed for select() */
void setnonblocking(sock)
int sock;
{
int opts;
opts = fcntl(sock,F_GETFL);
if (opts < 0) {
perror("fcntl(F_GETFL)");
exit(EXIT_FAILURE);
}
opts = (opts | O_NONBLOCK);
if (fcntl(sock,F_SETFL,opts) < 0) {
perror("fcntl(F_SETFL)");
exit(EXIT_FAILURE);
}
return;
}
void build_select_list()
{
int listnum; /* Current item in connectlist for for loops */
/* First put together fd_set for select(), which will
consist of the sock veriable in case a new connection
is coming in, plus all the sockets we have already
accepted. */
/* FD_ZERO() clears out the fd_set called socks, so that
it doesn't contain any file descriptors. */
FD_ZERO(&socks);
/* FD_SET() adds the file descriptor "sock" to the fd_set,
so that select() will return if a connection comes in
on that socket (which means you have to do accept(), etc. */
FD_SET(sock,&socks);
/* Loops through all the possible connections and adds
those sockets to the fd_set */
for (listnum = 0; listnum < 5; listnum++)
{
if (connectlist[listnum] != 0)
{
FD_SET(connectlist[listnum],&socks);
if (connectlist[listnum] > highsock)
highsock = connectlist[listnum];
}
}
}
void handle_new_connection()
{
int listnum; /* Current item in connectlist for for loops */
int connection; /* Socket file descriptor for incoming connections */
/* We have a new connection coming in! We'll
try to find a spot for it in connectlist. */
connection = accept(sock, NULL, NULL);
if (connection < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
setnonblocking(connection);
for (listnum = 0; (listnum < 5) && (connection != -1); listnum ++)
if (connectlist[listnum] == 0)
{
printf("/nConnection accepted: FD=%d; Slot=%d/n",
connection,listnum);
connectlist[listnum] = connection;
connection = -1;
}
if (connection != -1)
{
/* No room left in the queue! */
printf("/nNo room left for new client./n");
sock_puts(connection,"Sorry, this server is too busy. Try again later!/r/n");
close(connection);
}
}
void deal_with_data(int listnum)
/* Current item in connectlist for for loops */
{
char buffer[80]; /* Buffer for socket reads */
char *cur_char; /* Used in processing buffer */
if (sock_gets(connectlist[listnum],buffer,80) < 0)
{
/* Connection closed, close this end and free up entry in connectlist */
printf("/nConnection lost: FD=%d; Slot=%d/n", connectlist[listnum],listnum);
close(connectlist[listnum]);
connectlist[listnum] = 0;
}
else
{
/* We got some data, so upper case it
and send it back. */
printf("/nReceived: %s; ",buffer);
cur_char = buffer;
while (cur_char[0] != 0)
{
cur_char[0] = toupper(cur_char[0]);
cur_char++;
}
sock_puts(connectlist[listnum],buffer);
sock_puts(connectlist[listnum],"/n");
printf("responded: %s/n",buffer);
}
}
void read_socks()
{
int listnum;
/* Current item in connectlist for for loops */
/* OK, now socks will be set with whatever socket(s)
are ready for reading. Lets first check our
"listening" socket, and then check the sockets
in connectlist. */
/* If a client is trying to connect() to our listening
socket, select() will consider that as the socket
being 'readable'. Thus, if the listening socket is
part of the fd_set, we need to accept a new connection. */
if (FD_ISSET(sock,&socks))
handle_new_connection();
/* Now check connectlist for available data */
/* Run through our sockets and check to see if anything
happened with them, if so 'service' them. */
for (listnum = 0; listnum < 5; listnum++)
{
if (FD_ISSET(connectlist[listnum],&socks))
deal_with_data(listnum);
}
/* for (all entries in queue) */
}
int main (argc, argv)
int argc;
char *argv[];
{
char *ascport; /* ASCII version of the server port */
int port; /* The port number after conversion from ascport */
struct sockaddr_in server_address; /* bind info structure */
int reuse_addr = 1; /* Used so we can re-bind to our port
while a previous connection is still
in TIME_WAIT state. */
struct timeval timeout; /* Timeout for select */
int readsocks; /* Number of sockets ready for reading */
/* Make sure we got a port number as a parameter */
if (argc < 2) {
printf("Usage: %s PORT/r/n",argv[0]);
exit(EXIT_FAILURE);
}
/* Obtain a file descriptor for our "listening" socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror("socket");
exit(EXIT_FAILURE);
}
/* So that we can re-bind to it without TIME_WAIT problems */
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr));
/* Set socket to non-blocking with our setnonblocking routine */
setnonblocking(sock);
/* Get the address information, and bind it to the socket */
ascport = argv[1]; /* Read what the user gave us */
port = atoport(ascport); /* Use function from sockhelp to
convert to an int */
memset((char *) &server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = port;
if (bind(sock, (struct sockaddr *) &server_address,
sizeof(server_address)) < 0 )
{
perror("bind");
close(sock);
exit(EXIT_FAILURE);
}
/* Set up queue for incoming connections. */
listen(sock,5);
/* Since we start with only one socket, the listening socket,
it is the highest socket so far. */
highsock = sock;
memset((char *) &connectlist, 0, sizeof(connectlist));
while (1)
{ /* Main server loop - forever */
build_select_list();
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* The first argument to select is the highest file
descriptor value plus 1. In most cases, you can
just pass FD_SETSIZE and you'll be fine. */
/* The second argument to select() is the address of
the fd_set that contains sockets we're waiting
to be readable (including the listening socket). */
/* The third parameter is an fd_set that you want to
know if you can write on -- this example doesn't
use it, so it passes 0, or NULL. The fourth parameter
is sockets you're waiting for out-of-band data for,
which usually, you're not. */
/* The last parameter to select() is a time-out of how
long select() should block. If you want to wait forever
until something happens on a socket, you'll probably
want to pass NULL. */
readsocks = select(highsock+1, &socks, (fd_set *) 0,
(fd_set *) 0, &timeout);
/* select() returns the number of sockets that had
things going on with them -- i.e. they're readable. */
/* Once select() returns, the original fd_set has been
modified so it now reflects the state of why select()
woke up. i.e. If file descriptor 4 was originally in
the fd_set, and then it became readable, the fd_set
contains file descriptor 4 in it. */
if (readsocks < 0) {
perror("select");
exit(EXIT_FAILURE);
}
if (readsocks == 0) {
/* Nothing ready to read, just show that
we're alive */
printf(".");
fflush(stdout);
} else
read_socks();
} /* while(1) */
} /* main */
2.客户端程序
/* pollcli.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/un.h>
#include <sys/time.h>
#include <fcntl.h>
#define SOCKETNAME "/faculty/rossa/system/mysocket"