您的位置:首页 > 其它

select模型的实现

2012-08-01 20:30 218 查看
服务端:

#include "iostream.h"

#include "winsock2.h"

#pragma   comment   (lib,"ws2_32.lib")

#define DEFAULT_PORT 4000                  //默认端口号

void WINAPI SendOut();

char info[255];                            //服务器端控制台输入字符串

                           //是否有客户端连接

fd_set fds;

SOCKET sServSock;

int main()

{
WORD wVersionRequested=MAKEWORD(2,2);  //初始化Winsock
WSADATA wsaData;
WSAStartup(wVersionRequested,&wsaData);    //加载winsock库

    sServSock=socket(AF_INET,SOCK_STREAM,0);
sockaddr_in addr;
int nSockErr;

                     
SOCKET sClient;
sockaddr ConnAddr;
int nAddrLen=sizeof(sockaddr);
addr.sin_family=AF_INET;

    addr.sin_port=htons(DEFAULT_PORT);
addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
//绑定套接字到一个已知地址
if(bind(sServSock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR)
nSockErr=WSAGetLastError(); 
FD_ZERO(&fds);/*&*/

    FD_SET(sServSock,&fds);/*&*/

  //将套接字置入监听模式
if (listen(sServSock,5)==SOCKET_ERROR)
nSockErr=WSAGetLastError();
cout << "*****************Wait Client to Connect**********************" << endl;

  /*&*/

    bool bRunning=true;

      do {
   fd_set readfds;
   CopyMemory(&readfds,&fds,sizeof(fd_set));
  if(select(0,&readfds,NULL,NULL,NULL)>0)
  {
for(int i=readfds.fd_count-1;i>=0;i--)/* 顺序处理每一个有事件发生的套接字*/

               if(readfds.fd_array[i]==sServSock)

  {
             sClient=accept(sServSock,&ConnAddr,&nAddrLen);
             if(sClient==INVALID_SOCKET){
            bRunning=false;

            break;}
             cout<<"One of the Clients  Accept  Successful"<<endl;
 

             FD_SET(sClient,&fds);
/* 将与新客户端对应的套接字加入select函数监视的集合*/
             CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendOut,NULL,0,NULL);//发送数据
  }

             else // 与客户端对应的套接字有事件发生说明有数据需要接收
{
          char in[255];
          SOCKET sClient=readfds.fd_array[i];
          if(recv(sClient,in,255,0)!=SOCKET_ERROR)
         cout<<"\b<"<<in<<endl<<">";

               else{
               cout<<"\b<"<<"client exit"<<endl<<">";

                    FD_CLR(sClient,&fds);// 将该套接字移出select函数监视的集合
              closesocket(sClient);}
}
}

   } while(bRunning);

  WSACleanup();

/*&*/

  return 0;

}

//服务器发送函数

void WINAPI SendOut()

 {
   do {
     cin.getline(info,255);

     if(!strcmp(info,"bye")) break;

     cout<<">";

          for(int i=fds.fd_count-1;i>=0;i--)

                if( fds. fd_array [i]!=sServSock)
{
              fd_set writefds;
              FD_ZERO (&writefds);
              FD_SET(fds.fd_array[i],&writefds);
              if(select(0,NULL,&writefds,NULL,NULL)>0)
                 send(fds.fd_array[i],info,255,0);

}
} while(true);

      closesocket(sServSock);
 }

客户端:

#include "iostream.h"

#include "winsock2.h"

#define DEFAULT_PORT 4000                  //默认端口号

DWORD WINAPI ThreadFunc(LPVOID pParam);    //客户端socket接收线程函数

char info[255];                            //控制台输入字符串

void  main()

{
WORD wVersionRequested=MAKEWORD(2,2);  //初始化Winsock
WSADATA wsaData;
WSAStartup(wVersionRequested,&wsaData);     //加载winsock库
SOCKET sClntSock;
sockaddr_in addr;

    sockaddr_in ServAddr;
int nSockErr;

  //  sClntSock=socket(AF_INET,SOCK_DGRAM,0);

sClntSock=socket(AF_INET,SOCK_STREAM,0);
addr.sin_family=AF_INET;

    addr.sin_port=0;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
//绑定套接字到一个已知地址
if(bind(sClntSock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR)
nSockErr=WSAGetLastError();

ServAddr.sin_family=AF_INET;
ServAddr.sin_port=htons(DEFAULT_PORT);
cout<<"Please input the ip of server:";
char add_ip[50];
cin>>add_ip;
char dummy;
cin.get(dummy);

ServAddr.sin_addr.s_addr=inet_addr(add_ip);

    

    //连接服务器
if(connect(sClntSock,(const sockaddr*)(&ServAddr),sizeof(ServAddr))==SOCKET_ERROR)
{
  nSockErr=WSAGetLastError();
}
else cout<<"*****************Connect successful.****************"<<endl;

  //创建socket接收线程
CreateThread(NULL,0,ThreadFunc,&sClntSock,0,NULL);
//接收控制台输入并作相应操作
cout << ">";
cin.getline(info,255);
while(strcmp(info,"bye")){

        send(sClntSock,info,255,0);
cout << ">";
cin.getline(info,255);
}

                                   

}

//线程函数,接收网络消息

DWORD WINAPI ThreadFunc(LPVOID pParam)

{
SOCKET *s=(SOCKET *)pParam;
char in[255];
while(strcmp(info,"bye"))        //退出
{
if(recv(*s,in,255,0)!=SOCKET_ERROR)  //接收消息
{
cout << "\b" << in << endl << ">";
cout.flush();
}
else                         //出错,可能服务器死机 
{
cout<<"*****************Server Down*****************"<<endl;
exit(0);
}
}
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: