• C++非阻塞模式Socket编程


    iocServer.cpp:
    #include<WINSOCK2.H>
    #include<iostream>
    using namespace std;
    #include<stdlib.h>
    #define BUF_SIZE 64
    #pragma comment(lib,"WS2_32.lib")
    int main()
    {
    WSADATA wsd;
    SOCKET sServer;
    SOCKET sClient;
    int retVal;//调用Socket函数的返回值
    char buf[BUF_SIZE];


    //初始化Socket环境
    if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)
    {
    printf("WSAStartup failed! ");
    return 1;
    }
    //创建监听的Socket
    sServer=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(INVALID_SOCKET==sServer)
    {
    printf("socket failed! ");
    WSACleanup();
    return -1;
    }
    //设置服务器Socket地址
    SOCKADDR_IN addrServ;
    addrServ.sin_family=AF_INET;
    addrServ.sin_port=htons(9990);
    addrServ.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    //绑定Sockets Server
    retVal=bind(sServer,(const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN));
    if(SOCKET_ERROR==retVal)
    {
    printf("bind failed! ");
    closesocket(sServer);
    WSACleanup();
    return -1;
    }
    //在Sockets Server上进行监听
    retVal=listen(sServer,1);
    if(SOCKET_ERROR==retVal)
    {
    printf("listen failed! ");
    closesocket(sServer);
    WSACleanup();
    return -1;
    }
    //设置Socket为非阻塞模式
    int iMode = 1;
    retVal = ioctlsocket(sServer,FIONBIO,(u_long FAR*) &iMode);
    if(retVal == SOCKET_ERROR)
    {
    printf("ioctlsocket failed! ");
    WSACleanup();
    return -1;
    }
    //接受来自客户端的请求
    printf("TCPServer start... ");
    sockaddr_in addrClient;
    int addrClientlen=sizeof(addrClient);
    while(true)
    {
    sClient=accept(sServer,(sockaddr FAR*)&addrClient,&addrClientlen);
    if(INVALID_SOCKET == sClient)
    {
    int err = WSAGetLastError();
    if(err == WSAEWOULDBLOCK)
    {
    Sleep(5);
    continue;
    }
    else
    {
    printf("accept failed! ");
    closesocket(sServer);
    WSACleanup();
    return -1;
    }
    }
    break;
    }
    while(true)
    {
    ZeroMemory(buf,BUF_SIZE);
    retVal = recv(sClient,buf,BUF_SIZE,0);
    if(SOCKET_ERROR == retVal)
    {
    int err = WSAGetLastError();
    if(err == WSAEWOULDBLOCK)
    {
    Sleep(5);
    continue;
    }
    else if(err == WSAETIMEDOUT || err == WSAENETDOWN)
    {
    printf("recv failed! ");
    closesocket(sServer);
    closesocket(sClient);
    WSACleanup();
    return -1;
    }
    }
    SYSTEMTIME st;
    GetLocalTime(&st);
    char sDateTime[30];
    sprintf(sDateTime,"%4d-%2d-%2d-%2d:%2d:%2d:%2d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);
    //打印输出的信息
    printf("%s,Recv From Client [%s:%d]:%s ",sDateTime,inet_ntoa(addrClient.sin_addr),addrClient.sin_port,buf);
    //如果客户端发送quit字符串,则服务器退出
    if(strcmp(buf,"quit")==1)//////////////////////////////////////////
    {
    retVal=send(sClient,"quit",strlen("quit"),0);
    break;
    }
    //否则向客户端发送回显字符串
    else
    {
    char msg[BUF_SIZE];
    sprintf(msg,"Message received - %s ",buf);
    while(true)
    {
    retVal = send(sClient,msg,strlen(msg),0);
    if(SOCKET_ERROR == retVal)
    {
    int err = WSAGetLastError();
    if(err == WSAEWOULDBLOCK)
    {
    Sleep(5);
    continue;
    }
    else
    {
    printf("send failed! ");
    closesocket(sServer);
    closesocket(sClient);
    WSACleanup();
    return -1;
    }
    }
    }
    break;
    }
    }
    }
    iocClient.cpp:
    #include<WINSOCK2.H>
    #include<iostream>
    #include<string>
    using namespace std;
    #include<stdlib.h>
    #define BUF_SIZE 64
    #pragma comment(lib,"WS2_32.lib")
    int main()
    {
    WSADATA wsd;
    SOCKET sHost;
    SOCKADDR_IN servAddr;//服务器地址
    int retVal;//调用Socket函数的返回值
    char buf[BUF_SIZE];
    int iMode=1;
    //初始化Socket环境
    if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)
    {
    printf("WSAStartup failed! ");
    return -1;
    }
    sHost=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    //设置服务器Socket地址
    servAddr.sin_family=AF_INET;
    servAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
    //在实际应用中,建议将服务器的IP地址和端口号保存在配置文件中
    servAddr.sin_port=htons(9990);
    //计算地址的长度
    int sServerAddlen=sizeof(servAddr);
    //调用ioctlsocket()将其设置为非阻塞模式
    retVal=ioctlsocket(sHost,FIONBIO,(u_long FAR*)&iMode);
    if(retVal==SOCKET_ERROR)
    {
    printf("ioctlsocket failed!");
    WSACleanup();
    return -1;
    }


    //循环等待
    while(true)
    {
    //连接到服务器
    retVal=connect(sHost,(LPSOCKADDR)&servAddr,sizeof(servAddr));
    if(SOCKET_ERROR==retVal)
    {
    int err=WSAGetLastError();
    //无法立即完成非阻塞Socket上的操作
    if(err==WSAEWOULDBLOCK||err==WSAEINVAL)
    {
    Sleep(5);
    continue;
    }
    else if(err==WSAEISCONN)//已建立连接
    {
    break;
    }
    else
    {
    printf("connection failed! ");
    closesocket(sHost);
    WSACleanup();
    return -1;
    }
    }
    }
    while(true)
    {
    //向服务器发送字符串,并显示反馈信息
    printf("input a string to send: ");
    std::string str;
    //接收输入的数据
    std::getline(std::cin,str);
    //将用户输入的数据复制到buf中
    ZeroMemory(buf,BUF_SIZE);
    strcpy(buf,str.c_str());
    while(true)
    {
    retVal=send(sHost,buf,strlen(buf),0);
    if(SOCKET_ERROR==retVal)
    {
    int err=WSAGetLastError();
    if(err==WSAEWOULDBLOCK)
    {
    //无法立即完成非阻塞Socket上的操作
    Sleep(5);
    continue;
    }

    else
    {
    printf("send failed! ");
    closesocket(sHost);
    WSACleanup();
    return -1;
    }
    }
    break;
    }
    while(true)
    {
    ZeroMemory(buf,BUF_SIZE);//清空接收数据的缓冲区
    retVal=recv(sHost,buf,sizeof(buf)+1,0);
    if(SOCKET_ERROR==retVal)
    {
    int err=WSAGetLastError();
    //无法立即完成非阻塞Socket上的操作
    if(err==WSAEWOULDBLOCK)
    {
    Sleep(5000);
    printf("waiting back msg! ");
    continue;
    }
    else if(err==WSAETIMEDOUT||err==WSAENETDOWN)//已建立连接
    {
    printf("recv failed!");
    closesocket(sHost);
    WSACleanup();
    return -1;
    }
    break;
    }
    break;
    }
    ZeroMemory(buf,BUF_SIZE);
    retVal=recv(sHost,buf,sizeof(buf)+1,0);
    printf("Recv from Server:%s ",buf);
    //如果接收到quit,则退出
    if(strcmp(buf,"quit")==0)
    {
    printf("quit! ");
    break;
    }
    }
    return 0;
    }















































  • 相关阅读:
    验证整数或小数
    数据库的连接查询比较
    批处理按钮
    事务 SQL
    关于GridView模板的一些总结
    C#数据结构之线性表
    C#面向对象基础
    C#集合类:动态数组、队列、栈、哈希表、字典
    如何更改master中WebParts中自定义控件的值。
    如何取得web.config中connectings中的值
  • 原文地址:https://www.cnblogs.com/zhangaihua/p/3718091.html
Copyright © 2020-2023  润新知