select模型的实现

来源:互联网 发布:java输入异常处理 编辑:程序博客网 时间:2024/05/29 15:33

服务端:

#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;
}

原创粉丝点击