在网上下了utral vnc里面的repeater(repeater的作用是,在N个局域网中充当使者,进行通信),看了一下,里面实现的思路是Client与Server端配(即一个Server端的连接对应一个Client端的连接)对后开了一个线程去do_repeater,由于我用时是Server数量很少的,而Client很多,这样每开一个线程的话就会造成Server端很大的网络负担。现在我想这样,Server端在repeater里面只连接一次,而能通过repeater转发给这个Server对应的所有Client程序,我看了一下do_repeater函数,用了io模型,里面的对应关系看得我云里雾里的,希望有人能帮我一下。谢谢下面是do_repeater:(local_in,local_out都是client连接套接字,remote是Server端连接进来的套接字)
DWORD WINAPI do_repeater(LPVOID lpParam)
{
    /** vars for local input data **/
    char lbuf[1029]; /* local input buffer */
    int lbuf_len=0; /* available data in lbuf */
    int f_local; /* read local input more? */
    /** vars for remote input data **/
    char rbuf[1029]; /* remote input buffer */
    int rbuf_len; /* available data in rbuf */
    int f_remote; /* read remote input more? */
    /** other variables **/
    int nfds, len;
    fd_set *ifds, *ofds;
    struct timeval *tmo;
//    struct timeval win32_tmo;

SOCKET local_in=0;
SOCKET local_out=0;
SOCKET remote=0;
ULONG code=0;
long recvbytes=0;
long sendbytes=0; 
int nummer;
pmystruct inout=(pmystruct)lpParam;
    local_in=inout->local_in;
local_out=inout->local_out;
remote=inout->remote;
code=inout->code;
nummer=inout->nummer;
LogStats2(code);
lbuf_len = 0;
    rbuf_len = 0; if (inout->server) 
{
memcpy(lbuf,Viewers[nummer].preloadbuffer,Viewers[nummer].size_buffer);
lbuf_len=Viewers[nummer].size_buffer;
Viewers[nummer].size_buffer=0;
}
else
{
memcpy(lbuf,Servers[nummer].preloadbuffer,Servers[nummer].size_buffer);
lbuf_len=Servers[nummer].size_buffer;
Servers[nummer].size_buffer=0;
} if ( 0 < lbuf_len ) 
{
    if (inout->server) len = send(remote, lbuf, lbuf_len, 0);
else len = send(local_in, lbuf, lbuf_len, 0);
    if ( 1 < f_debug ) //* more verbose 
report_bytes( ">>>", lbuf, lbuf_len);
    if ( len == -1 ) {
debug("send() failed, %d\n", socket_errno());
goto error;
    } else if ( 0 < len ) {
//* move data on to top of buffer 
sendbytes+=len;
lbuf_len -= len;
if ( 0 < lbuf_len )
    memcpy( lbuf, lbuf+len, lbuf_len );
assert( 0 <= lbuf_len );
    }
}
LogStats2(code);
    /* repeater between stdin/out and socket  */
    nfds = ((local_in<remote)? remote: local_in) +1;
    ifds = FD_ALLOC(nfds);
    ofds = FD_ALLOC(nfds);
    f_local = 1; /* yes, read from local */
    f_remote = 1; /* yes, read from remote */    while ( f_local || f_remote ) {
FD_ZERO( ifds );
FD_ZERO( ofds );
tmo = NULL; /** prepare for reading local input **/
if ( f_local && (lbuf_len < sizeof(lbuf)) ) {
    FD_SET( local_in, ifds );
}

/** prepare for reading remote input **/
if ( f_remote && (rbuf_len < sizeof(rbuf)) ) {
    FD_SET( remote, ifds );
}

/* FD_SET( local_out, ofds ); */
/* FD_SET( remote, ofds ); */

if ( select( nfds, ifds, ofds, NULL, tmo ) == -1 ) {
    /* some error */
    error( "select() failed, %d\n", socket_errno());
goto error;
}
/* fake ifds if local is stdio handle because
           select() of Winsock does not accept stdio
           handle. */ /* remote => local */
if ( FD_ISSET(remote, ifds) && (rbuf_len < sizeof(rbuf)) ) {
    len = recv( remote, rbuf + rbuf_len, sizeof(rbuf)-rbuf_len, 0);
    if ( len == 0 ) {
debug("connection closed by peer\n");
goto error;     } else if ( len == -1 ) {
if (socket_errno() != ECONNRESET) {
    /* error */
    fatal("recv() faield, %d\n", socket_errno());
goto error;
} else {
    debug("ECONNRESET detected\n");
goto error;
}
    } else {
recvbytes +=len;
if ( 1 < f_debug ) /* more verbose */
    report_bytes( "<<<", rbuf, rbuf_len);
rbuf_len += len;
    }
}

/* local => remote */
if ( FD_ISSET(local_in, ifds) && (lbuf_len < sizeof(lbuf)) ) { len = recv(local_in, lbuf + lbuf_len,sizeof(lbuf)-lbuf_len, 0);     if ( len == 0 ) {
/* stdin is EOF */
debug("local input is EOF\n");
goto error;
    } else if ( len == -1 ) {
/* error on reading from stdin */
goto error;
    } else {
/* repeat */
lbuf_len += len;
    }
}

/* flush data in buffer to socket */
if ( 0 < lbuf_len ) {
    len = send(remote, lbuf, lbuf_len, 0);
    if ( 1 < f_debug ) /* more verbose */
report_bytes( ">>>", lbuf, lbuf_len);
    if ( len == -1 ) {
debug("send() failed, %d\n", socket_errno());
goto error;
    } else if ( 0 < len ) {
/* move data on to top of buffer */
sendbytes+=len;
lbuf_len -= len;
if ( 0 < lbuf_len )
    memcpy( lbuf, lbuf+len, lbuf_len );
assert( 0 <= lbuf_len );
    }
}

/* flush data in buffer to local output */
if ( 0 < rbuf_len ) { len = send( local_out, rbuf, rbuf_len, 0);
    if ( len == -1 ) {
debug("output (local) failed, errno=%d\n", errno);
goto error;
    } 
else
{
    rbuf_len -= len;
    if ( len < rbuf_len )
memcpy( rbuf, rbuf+len, rbuf_len );
    assert( 0 <= rbuf_len );
}
}    }
error:
LogStats(code,recvbytes,sendbytes);
f_remote = 0; /* no more read from socket */
f_local = 0;
closesocket(local_in);
closesocket(remote);
shutdown(local_in, 1);
shutdown(remote, 1);
local_in=0;
remote=0;
    Remove_server_list(code);
Remove_viewer_list(code);
    return 0;
}