select模型使用例子

在windows平台构建网络应用,必须了解socket I/O模型。windows提供了选择(select)、异步选择(WSAAsyncSelect)、事件选择(WSAEventSelect)、重叠I /O(overlapped I/O)和完成端口(completion port)。 

一、客户端代码

C++代码  

#include <WINSOCK2.H>   

#include <stdio.h>   

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

#define SERVER_ADDRESS  "192.168.10.56"   

#define PORT  5150   

#define MSGSIZE  1024   

int main(int argc, char* argv[])   

{   

    WSADATA wsaData;   

    SOCKET sClient;   

    SOCKADDR_IN server;   

    char szMessage[MSGSIZE];   

    int ret;   

    // Initialize windows socket library   

    WSAStartup(0x0202, &wsaData);   

    // Create client socket   

    sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   

    // Connect to server   

    memset(&server, 0, sizeof(SOCKADDR_IN));   

    server.sin_family = AF_INET;   

    server.sin_addr.S_un.S_addr = inet_addr(SERVER_ADDRESS);   

    server.sin_port = htons(PORT);   

    connect(sClient, (sockaddr*)&server, sizeof(SOCKADDR_IN));   

    while (TRUE)    

    {   

        printf("Send:");   

        gets(szMessage);   

        // Send message   

        send(sClient, szMessage, strlen(szMessage), 0);   

        // Receive message   

        ret = recv(sClient, szMessage, MSGSIZE, 0);   

        szMessage[ret] = '/0';   

        printf("Received [%d bytes]: '%s'/n", ret, szMessage);   

    }   

    // Clean up   

    closesocket(sClient);   

    WSACleanup();   

    return 0;   

}  

[C++] view plaincopy

#include "stdafx.h"  

#include <WINSOCK2.H>  

#include <stdio.h>  

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

#define SERVER_ADDRESS  "192.168.10.56"  

#define PORT  5150  

#define MSGSIZE  1024  

int main(int argc, char* argv[])  

{  

    WSADATA wsaData;  

    SOCKET sClient;  

    SOCKADDR_IN server;  

    char szMessage[MSGSIZE];  

    int ret;  

    // Initialize windows socket library  

    WSAStartup(0x0202, &wsaData);  

    // Create client socket  

    sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  

    // Connect to server  

    memset(&server, 0, sizeof(SOCKADDR_IN));  

    server.sin_family = AF_INET;  

    server.sin_addr.S_un.S_addr = inet_addr(SERVER_ADDRESS);  

    server.sin_port = htons(PORT);  

    connect(sClient, (sockaddr*)&server, sizeof(SOCKADDR_IN));  

    while (TRUE)   

    {  

        printf("Send:");  

        gets(szMessage);  

        // Send message  

        send(sClient, szMessage, strlen(szMessage), 0);  

        // Receive message  

        ret = recv(sClient, szMessage, MSGSIZE, 0);  

        szMessage[ret] = '/0';  

        printf("Received [%d bytes]: '%s'/n", ret, szMessage);  

    }  

    // Clean up  

    closesocket(sClient);  

    WSACleanup();  

    return 0;  

}  

这是一个最简单的客户端代码,负责发送数据,然后接受返回。 

二、使用select模型的服务器

C++代码 

// write by larry   

// 2009-8-20   

// This is server using select model.   

#include "stdafx.h"   

#include <winsock.h>   

#include <stdio.h>   

#define PORT  5150   

#define MSGSIZE  1024   

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

int g_iTotalConn = 0;   

SOCKET g_CliSocketArr[FD_SETSIZE];   

DWORD WINAPI WorkerThread(LPVOID lpParam);   

int main(int argc, char* argv[])   

{   

    WSADATA wsaData;   

    SOCKET sListen, sClient;   

    SOCKADDR_IN local, client;   

    int iAddrSize = sizeof(SOCKADDR_IN);   

    DWORD dwThreadId;   

    // Initialize windows socket library   

    WSAStartup(0x0202, &wsaData);   

    // Create listening socket   

    sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   

    // Bind   

    local.sin_family = AF_INET;   

    local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);   

    local.sin_port = htons(PORT);   

    bind(sListen, (sockaddr*)&local, sizeof(SOCKADDR_IN));   

    // Listen   

    listen(sListen, 3);   

    // Create worker thread   

    CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);   

    while (TRUE)    

    {   

        // Accept a connection   

        sClient = accept(sListen, (sockaddr*)&client, &iAddrSize);   

        printf("Accepted client:%s:%d/n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));   

        // Add socket to g_CliSocketArr   

        g_CliSocketArr[g_iTotalConn++] = sClient;   

    }   

    return 0;   

}   

DWORD WINAPI WorkerThread(LPVOID lpParam)   

{   

    int i;   

    fd_set fdread;   

    int ret;   

    struct timeval tv = {1, 0};   

    char szMessage[MSGSIZE];   

    while (TRUE)    

    {   

        FD_ZERO(&fdread);   

        for (i = 0; i < g_iTotalConn; i++)    

        {   

            FD_SET(g_CliSocketArr[i], &fdread);   

        }   

        // We only care read event   

        ret = select(0, &fdread, NULL, NULL, &tv);   

        if (ret == 0)    

        {   

            // Time expired   

            continue;   

        }   

        for (i = 0; i < g_iTotalConn; i++)    

        {   

            if (FD_ISSET(g_CliSocketArr[i], &fdread))    

            {   

                // A read event happened on g_CliSocketArr   

                ret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0);   

                if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))    

                {   

                    // Client socket closed   

                    printf("Client socket %d closed./n", g_CliSocketArr[i]);   

                    closesocket(g_CliSocketArr[i]);   

                    if (i < g_iTotalConn-1)    

                    {   

                        g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];   

                    }   

                }    

                else    

                {   

                    // We reveived a message from client   

                    szMessage[ret] = '/0';   

                    send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);   

                }     }     }       }   

}  

[C++] // write by larry  

// 2009-8-20  

// This is server using select model.  

#include "stdafx.h"  

#include <winsock.h>  

#include <stdio.h>  

#define PORT  5150  

#define MSGSIZE  1024  

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

int g_iTotalConn = 0;  

SOCKET g_CliSocketArr[FD_SETSIZE];  

DWORD WINAPI WorkerThread(LPVOID lpParam);  

int main(int argc, char* argv[])  

{  

    WSADATA wsaData;  

    SOCKET sListen, sClient;  

    SOCKADDR_IN local, client;  

    int iAddrSize = sizeof(SOCKADDR_IN);  

    DWORD dwThreadId;  

    // Initialize windows socket library  

    WSAStartup(0x0202, &wsaData);  

    // Create listening socket  

    sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  

    // Bind  

    local.sin_family = AF_INET;  

    local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);  

    local.sin_port = htons(PORT);  

    bind(sListen, (sockaddr*)&local, sizeof(SOCKADDR_IN));  

    // Listen  

    listen(sListen, 3);  

    // Create worker thread  

    CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);  

    while (TRUE)   

    {  

        // Accept a connection  

        sClient = accept(sListen, (sockaddr*)&client, &iAddrSize);  

        printf("Accepted client:%s:%d/n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));  

        // Add socket to g_CliSocketArr  

        g_CliSocketArr[g_iTotalConn++] = sClient;  

    }  

    return 0;  

}  

DWORD WINAPI WorkerThread(LPVOID lpParam)  

{  

    int i;  

    fd_set fdread;  

    int ret;  

    struct timeval tv = {1, 0};  

    char szMessage[MSGSIZE];  

    while (TRUE)   

    {  

        FD_ZERO(&fdread);  

        for (i = 0; i < g_iTotalConn; i++)   

        {  

            FD_SET(g_CliSocketArr[i], &fdread);  

        }  

        // We only care read event  

        ret = select(0, &fdread, NULL, NULL, &tv);  

        if (ret == 0)   

        {  

            // Time expired  

            continue;  

        }  

        for (i = 0; i < g_iTotalConn; i++)   

        {  

            if (FD_ISSET(g_CliSocketArr[i], &fdread))   

            {  

                // A read event happened on g_CliSocketArr  

                ret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0);  

                if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))   

                {  

                    // Client socket closed  

                    printf("Client socket %d closed./n", g_CliSocketArr[i]);  

                    closesocket(g_CliSocketArr[i]);  

                    if (i < g_iTotalConn-1)   

                    {  

                        g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];  

                    }  

                }   

                else   

                {  

                    // We reveived a message from client  

                    szMessage[ret] = '/0';  

                    send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);  

                }  }    }     }  

}  这是异步模型中最简单的一种,服务器端的几个主要流程如下: 

1.创建监听套接字,绑定,监听;2.创建工作者线程;3.创建一个套接字数组,用来存放当前所有活动的客户端套接字,每accept一个连接就更新一次数组; 4.接受客户端的连接。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值