您的位置:首页 > 其它

Windows socket I/O模型 之 select(1)

2014-04-11 10:50 120 查看
参考1:http://blog.csdn.net/zjsiva/article/details/5895087

我喜欢直接上代码,请看,在上述代码增加了一些内容。

比如服务器自动回复客户机请求。

// 服务器

// Select_Server.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <stdio.h>
#include <string.h>
#include <WINSOCK2.H>

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

#define STR_SERVER_IP           "127.0.0.1"
#define INT_SERVER_PORT         6002
#define INT_DATABUFFER_SIZE     256

int _tmain(int argc, _TCHAR* argv[])
{
    WORD dwVersion = MAKEWORD(2,2);
    WSAData wsaData;
    WSAStartup(WINSOCK_VERSION,&wsaData);

    SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);
    if (INVALID_SOCKET == sockServer) {
        printf("Failed to create socket!\r\n");
        WSACleanup();
        return -1;
    }

    sockaddr_in addrServer;
    memset(&addrServer,0,sizeof(sockaddr_in));
    addrServer.sin_family = AF_INET;
    addrServer.sin_port = htons(INT_SERVER_PORT);
    addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    //addrServer.sin_addr.s_addr = htonl(INADDR_ANY);

    int iResult;

    bool bReuseAddr = true;
    iResult=setsockopt(sockServer,SOL_SOCKET,SO_REUSEADDR,(char *)&bReuseAddr,sizeof(bReuseAddr));
    if(SOCKET_ERROR == iResult) {
        printf("Failed to set resueaddr socket!\r\n");
        WSACleanup();
        return -1;
    }

    /*
    unsigned   long cmd = 1;
    iResult= ioctlsocket(sockServer,FIONBIO,&cmd); */

    iResult = bind(sockServer,(sockaddr *)&addrServer,sizeof(addrServer));
    if (SOCKET_ERROR == iResult) {
        printf("Failed to bind address!\r\n");
        WSACleanup();
        return -1;
    }

    if (0 != listen(sockServer,5)) {
        printf("Failed to listen client!\r\n");
        WSACleanup();
        return -1;
    }

    UINT i = 0;
    SOCKET sockAccept;
    sockaddr_in addrAccept;
    int iAcceptLen = sizeof(addrAccept);
    char szDataBuff[INT_DATABUFFER_SIZE];
    int iRecvSize;

    sockaddr_in addrTemp;
    int iTempLen;

    fd_set fd;
    FD_ZERO(&fd);
    FD_SET(sockServer, &fd);

    /*
    timeval tm;
    tm.tv_sec = 0;
    tm.tv_usec = 1000;
    */
    printf("Start server...\r\n");
    while(1) {
        fd_set fdOld = fd;
        iResult = select(0, &fdOld, NULL, NULL, /*&tm*/NULL);
        if (0 <= iResult) {
            for(i = 0; i < fd.fd_count; i++) {
                if (FD_ISSET(fd.fd_array[i], &fdOld)) {
                    //如果socket是服务器,则接收连接
                    if (fd.fd_array[i] == sockServer) {
                        memset(&addrAccept,0,sizeof(addrTemp));
                        sockAccept = accept(sockServer, (sockaddr *)&addrAccept, &iAcceptLen);
                        if (INVALID_SOCKET != sockAccept) {
                            FD_SET(sockAccept, &fd);
                            //FD_SET(sockAccept,&fdOld);
                            printf("%s:%d has connected server!\r\n", inet_ntoa(addrAccept.sin_addr),
                                ntohs(addrAccept.sin_port));
                        }
                    } else { //非服务器,接收数据(因为fd是读数据集)
                        memset(szDataBuff, 0, INT_DATABUFFER_SIZE);
                        iRecvSize = recv(fd.fd_array[i], szDataBuff, INT_DATABUFFER_SIZE, 0);

                        memset(&addrTemp, 0, sizeof(addrTemp));
                        iTempLen = sizeof(addrTemp);
                        getpeername(fd.fd_array[i], (sockaddr *)&addrTemp, &iTempLen);

                        // an error occurs
                        if (SOCKET_ERROR == iRecvSize) {
                            closesocket(fd.fd_array[i]);
                            FD_CLR(fd.fd_array[i], &fd);
                            i--;
                            printf("Failed to recv data ,%s:%d errorcode:%d.\r\n",
                                inet_ntoa(addrTemp.sin_addr),ntohs(addrTemp.sin_port),WSAGetLastError());
                            continue;
                        }

                        // 客户socket关闭
                        if (0 == iRecvSize) {
                            printf("%s:%d has closed!\r\n",inet_ntoa(addrTemp.sin_addr),
                                ntohs(addrTemp.sin_port));

                            closesocket(fd.fd_array[i]);
                            FD_CLR(fd.fd_array[i],&fd);
                            i--;
                        }

                        // no error occurs, returns the number of bytes received
                        if (0 < iRecvSize) {
                            printf("recv %s:%d data:%s\r\n", inet_ntoa(addrTemp.sin_addr),
                                ntohs(addrTemp.sin_port),szDataBuff);
                            char szEcho[256] = {0};
                            sprintf(szEcho, "Server has got: %s.", szDataBuff);
                            send(fd.fd_array[i], szEcho, strlen(szEcho), 0);
                        }
                    }
                }
            }
        } else if (SOCKET_ERROR == iResult) {
            int iErr = WSAGetLastError();
            //WSACleanup();
            printf("Faild to select sockt in server!(Error: %d)\r\n", iErr);
            Sleep(100);
        }
    }
    WSACleanup();

    return 0;
}


// 客户机

// Select_Client.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <stdio.h>
#include <string.h>
#include <WINSOCK2.H>

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

#define INT_SERVER_PORT 6002
#define STR_SERVER_IP "127.0.0.1"
#define INT_DATABUFFER_SIZE 256
#define STR_EXIT "exit"
#define STR_RECV "recv"
void main(void)
{
    WSAData wsaData;
    WSAStartup(WINSOCK_VERSION,&wsaData);
  
    SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);
    if (INVALID_SOCKET == sockClient) {
        printf("Failed to create client!\r\n");
        WSACleanup();
    }
  
    sockaddr_in addrClient;
    addrClient.sin_addr.S_un.S_addr = inet_addr(STR_SERVER_IP);
    addrClient.sin_family = AF_INET;
    addrClient.sin_port = htons(INT_SERVER_PORT);
  
      
    int iResult;
    iResult = connect(sockClient,(sockaddr *)&addrClient,sizeof(sockaddr_in));
    if (SOCKET_ERROR == iResult) {
        printf("Failed to connect server!\r\n");
        WSACleanup();
        return;
    }
  
    if (0 != iResult) {
        int iErrorCode;
        iErrorCode = WSAGetLastError();
        printf("Failed to connect server,error:%d.\r\n",iErrorCode);
        WSACleanup();
        return;
    }
    char szDataBuffer[INT_DATABUFFER_SIZE];
    while(1) {
        memset(szDataBuffer,0,INT_DATABUFFER_SIZE);
        scanf("%s",szDataBuffer);
  
        if (0 == strcmp(szDataBuffer, STR_EXIT)) {
            printf("The client has stopped!\r\n");
            break;
        } else if( 0 == strcmp(szDataBuffer, STR_RECV)) {
            int ret = recv(sockClient, szDataBuffer, 256, 0);
            printf("Recv server echo: %s\r\n", szDataBuffer);
        } else {
            if (1 > send(sockClient, szDataBuffer, strlen(szDataBuffer),0)) {
                printf("Failed to send data!\r\n");
            }
        }
        Sleep(100);
    }
    closesocket(sockClient);
    WSACleanup();
}
这里需要注意的就是 fd_set, FD_ZERO,FD_SET,FD_ISSET这几个宏的用法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: