欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

因为当需要探测 劳务派遣信息管理系统 的句柄值较大时

点击: 次  来源:宝鼎软件 时间:2017-05-31

原文出处: 阿凡卢

一些观念:

同步和异步

同步和异步是针对应用措施和内核的交互而言的,同步指的是用户历程触发I/O操纵并期待可能轮询的去查察I/O操纵是否停当,而异步是指用户历程触发I/O操纵今后便开始做本身的工作,而当I/O操纵已经完成的时候会获得I/O完成的通知。

阻塞和非阻塞

阻塞和非阻塞是针对付历程在会见数据的时候,按照I/O操纵的停当状态来采纳的差异方法,说白了是一种读取可能写入操纵函数的实现方法,阻塞方法下读取可能写入函数将一直期待,而非阻塞方法下,读取可能写入函数会当即返回一个状态值。

处事器端几种模子:

1、阻塞式模子(blocking IO)

我们第一次打仗到的网络编程都是从 listen()、accpet()、send()、recv() 等接口开始的。利用这些接口可以很利便的构建C/S的模子。这里大部门的 socket 接口都是阻塞型的。所谓阻塞型接口是指系统挪用(一般是 IO 接口)不返回挪用功效并让当前线程一直阻塞,只有当该系统挪用得到功效可能超时堕落时才返回。

如下面一个简朴的Server端实现:

#include <Winsock2.h>
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

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

int init_win_socket()
{
    WSADATA wsaData;

    if(WSAStartup(MAKEWORD(2,2) , &wsaData ) != 0) 
    {
        return -1;
    }

    return 0;
}

#define Server_Port 10286

void handle_client(int newfd)
{
    while(1)
    {
        char buff[1024];
        memset(buff,0,1024);
        int result = recv(newfd,buff,1024,0);
        if(result <= 0)
        {
            break;
        }
        else
        {
            printf("Receive Data %s, Size: %d \n",buff,result);
            int ret = send(newfd,buff,result,0);
            if(ret>0)
            {
                printf("Send Data %s, Size: %d \n",buff,ret);
            }
            else
            {
                break;
            }
        }
    }
    closesocket(newfd);
    return;
}

int run()
{
    int listener;
    struct sockaddr_in addr_server;

    listener = socket(AF_INET, SOCK_STREAM, 0);

    //addr_server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addr_server.sin_addr.S_un.S_addr = ADDR_ANY;
    addr_server.sin_family = AF_INET;
    addr_server.sin_port = htons(Server_Port);

    if(bind(listener,(const sockaddr *)&addr_server,sizeof(addr_server)) < 0)
    {
        perror("bind error");
        return -1;
    }

    if (listen(listener, 10)<0) 
    {
        perror("listen error");
        return -1;
    }

    printf("Server is listening ... \n");

    bool runing = true;
    while(runing)
    {
        sockaddr_in addr_client;
        int clientlen = sizeof(addr_client);
        int client_sock;
        if ((client_sock = accept(listener, (struct sockaddr *) &addr_client, &clientlen)) < 0) 
        {
            printf("Failed to accept client connection \n");
        }
        fprintf(stdout, "Client connected: %s \n", inet_ntoa(addr_client.sin_addr));
        /*Handle this connect */
        handle_client(client_sock);
    }

    closesocket(listener);
    return 0;
}

int main(int c, char **v)
{

#ifdef WIN32
    init_win_socket();
#endif

    run();

    getchar();
    return 0;
}

示意图如下:

因为当需要探测 劳务调派信息打点系统 的句柄值较大时 这里的socket的接口是阻塞的(blocking),在线程被阻塞期间,线程将无法执行任何运算或响应任何的网络请求,这给多客户机、多业务逻辑的网络编程带来了挑战。

2、多线程的处事器模子(Multi-Thread)

应对多客户机的网络应用,最简朴的办理方法是在处事器端利用多线程(或多历程)。多线程(或多历程)的目标是让每个毗连都拥有独立的线程(或历程),这样任何一个毗连的阻塞都不会影响其他的毗连。

多线程Server端的实现:

#include <Winsock2.h>
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

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

int init_win_socket()
{
    WSADATA wsaData;

    if(WSAStartup(MAKEWORD(2,2) , &wsaData ) != 0) 
    {
        return -1;
    }

    return 0;
}

#define Server_Port 10286

DWORD WINAPI handle_client(LPVOID lppara)
{
    int *newfd = (int *)lppara;
    while(1)
    {
        char buff[1024];
        memset(buff,0,1024);
        int result = recv(*newfd,buff,1024,0);
        if(result <= 0)
        {
            break;
        }
        else
        {
            printf("Receive Data %s, Size: %d \n",buff,result);
            int ret = send(*newfd,buff,result,0);
            if(ret>0)
            {
                printf("Send Data %s, Size: %d \n",buff,ret);
            }
            else
            {
                break;
            }
        }
        Sleep(10);
    }
    closesocket(*newfd);
    return 0;
}

int run()
{
    int listener;
    struct sockaddr_in addr_server;
    int sock_clients[1024]; //max number for accept client connection;

    listener = socket(AF_INET, SOCK_STREAM, 0);

    //addr_server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addr_server.sin_addr.S_un.S_addr = ADDR_ANY;
    addr_server.sin_family = AF_INET;
    addr_server.sin_port = htons(Server_Port);

    if(bind(listener,(const sockaddr *)&addr_server,sizeof(addr_server)) < 0)
    {
        perror("bind error");
        return -1;
    }

    if (listen(listener, 10)<0) 
    {
        perror("listen error");
        return -1;
    }

    printf("Server is listening ... \n");

    int fd_count = 0;
    bool runing = true;
    while(runing)
    {
        sockaddr_in addr_client;
        int clientlen = sizeof(addr_client);
        int client_sock;
        if ((client_sock = accept(listener, (struct sockaddr *) &addr_client, &clientlen)) < 0) 
        {
            printf("Failed to accept client connection \n");
        }
        fprintf(stdout, "Client connected: socket fd %d , %s \n", client_sock,inet_ntoa(addr_client.sin_addr));
        /*Handle this connect */
        if(fd_count<1024)
        {
            sock_clients[fd_count] = client_sock;
            if(CreateThread(NULL,0,handle_client,&sock_clients[fd_count],0,NULL)==NULL)
                return -1;
            ++ fd_count;
        }

        Sleep(10);
    }

    closesocket(listener);
    return 0;
}

int main(int c, char **v)
{

#ifdef WIN32
    init_win_socket();
#endif

    run();

    getchar();
    return 0;
}