前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >网络编程基础第四讲阻塞模型

网络编程基础第四讲阻塞模型

作者头像
IBinary
发布2019-05-25 16:20:32
3170
发布2019-05-25 16:20:32
举报
文章被收录于专栏:逆向技术逆向技术逆向技术

      网络编程基础第四讲阻塞模型

一丶阻塞模型简介

  不知道大家有没有注意到.我们客户端 或者服务端.的TCP 收发数据的时候(send/recv)如果接受不到数据就一直不返回.从而造成我们网络的阻塞.程序无法正常执行.

不过针对这一方法.我们可以开一个线程去专门接受数据.或者发送数据.

这个就是我们常说的阻塞.

只要我们创建的套接字都是阻塞模型. 就是说数据接受不到不返回.

我们可以设置为非阻塞.就是不管数据有没有来到都会返回.如果来到.会有通知.我们可以编程接受数据.

设置非阻塞模式方法

  ioctlsocket(SOCKET s, long cmd, u_long *arpg);

改变套接字模式.为飞租she.

二丶阻塞模式迭代模式 与 并发连接模式

  1.阻塞模式的迭代模式 就是指每次只服务一个连接.只有服务完当前的客户端连接之后.才会继续服务下一个客户连接

  2.并发连接模式 通过多线程.可以同时服务多个链接.没一个线程处理一个客户端的连接.

阻塞迭代模式步骤

  1.生成一个函数.绑定本地地址跟监听.

  2.生成一个函数.专门接受一个客户端连接.并且返回对应连接的套接字.

  3.处理没一个客户端的连接.实现接受跟发送数据.

  4.关闭一个连接.

其实就是讲创建服务端网络做了一个封装.

如下代码. 一个.h文件.存放函数声明.一个.cpp封装了网络连接的代码.

.h文件:

#pragma once
#include "stdafx.h"
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;


#include "initSocket.h"

void DebugLog(TCHAR *str);
//初始化数据
int initSocket();

//1.创建套接字.绑定地址,开始监听
SOCKET BindAnListen(int nBacklog);

//接受连接分装

SOCKET AccepeConnect(SOCKET hSocket);

//接受跟发送数据
BOOL ClientReadAnWriteData(SOCKET hSocket);

//关闭数据连接
BOOL ColseConnect(SOCKET hSocket);

.cpp实现.

#include "initSocket.h"

void DebugLog(TCHAR *str)
{
    cout << str << WSAGetLastError() << endl;
}
//初始化数据
int initSocket()
{
    WSADATA data;
    if (WSAStartup(MAKEWORD(2, 2), &data))
    {
        DebugLog(TEXT("initsocket faile"));
        return 0;
    }
}

//1.创建套接字.绑定地址,开始监听
SOCKET BindAnListen(int nBacklog)
{
    //创建套接字
    BOOL bRet = FALSE;
    SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (INVALID_SOCKET == hSocket)
    {
        DebugLog(TEXT("BindAnListen Fail"));
        return INVALID_SOCKET;
    }
                
    //绑定套接字
    sockaddr_in addr;
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    //htonl addr_any
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8524);
    bRet =  bind(hSocket, (sockaddr *)&addr, sizeof(addr));
    if (SOCKET_ERROR == bRet)
    {

        DebugLog(TEXT("bind fail"));
        closesocket(hSocket);
        WSACleanup();
        return INVALID_SOCKET;
    }
    //监听套接字
    bRet = FALSE;
    bRet =  listen(hSocket, nBacklog);
    if (SOCKET_ERROR ==bRet)
    {
        DebugLog(TEXT("Listen fail"));
        closesocket(hSocket);
        WSACleanup();
        return INVALID_SOCKET;
    }
    return hSocket;
}

//接受连接分装

SOCKET AccepeConnect(SOCKET hSocket)
{
    sockaddr_in addr;
    int nSize = sizeof(addr);
    SOCKET hNewSocket = accept(hSocket, (LPSOCKADDR)&addr, &nSize);
    if (hNewSocket == INVALID_SOCKET)
    {

        DebugLog(TEXT("Accept An Connect Fail"));
        return INVALID_SOCKET;
    }
    return hNewSocket;
}

//接受跟发送数据
BOOL ClientReadAnWriteData(SOCKET hSocket)
{
    char szBuffer[1024] = { NULL };
    int nBufferSzie = sizeof(szBuffer);
    //循环处理数据
    int nRecvBytes = 0;
    do
    {
        nRecvBytes = recv(hSocket,szBuffer, nBufferSzie, 0);
        if (SOCKET_ERROR == nRecvBytes)
        {

            DebugLog(TEXT("Recv Data Fail"));
            return FALSE;
        }
        else if (0 != nRecvBytes)
        {
       szBuffer[nRecvBytes] = 0;     
            cout << "接受到的数据为: " << szBuffer << endl;
            //接着循环发送回去.
            int nSendDataBytes = 0;
            while (nSendDataBytes < nRecvBytes)
            {
                int nRetValue = send(hSocket, szBuffer, nBufferSzie, 0);
                if (nRetValue > 0)
                {
                    nSendDataBytes = nSendDataBytes + nRetValue;
                    //每次发送的数据都增加.这样就会发送过去了

                }
                else if (nRetValue == SOCKET_ERROR)
                {
                    DebugLog(TEXT("发送数据失败"));
                    return FALSE;
                }
                else
                {
                    //send 返回0 也就是send失败了.客户端关闭了
                    DebugLog(TEXT("发送数据失败,客户端已经关闭了"));
                    return FALSE;
                }


            }
        }

    } while (0 != nRecvBytes);
    return FALSE;
}

BOOL ColseConnect(SOCKET hSocket)
{
    //shutdown 跟 closesocket一样.不过 TCP 会发送一个FIN分段.给对方表名已经完成数据发送
    if (shutdown(hSocket,SD_SEND) == SOCKET_ERROR)
    {
        DebugLog(TEXT("关闭连接失败"));
        return FALSE;
    }
    //注意.客户端会发送一个数据.不写也可以.
    return TRUE;
}

上面的代码只是把我们网络创建的一些步骤给封装了.并没有实际编写我们用的代码.

在main函数中使用.只服务一个socket操作

// Server.cpp : 定义控制台应用程序的入口点。
//

#include "initSocket.h"


int main()
{
    //初始化
    initSocket();
    //1.绑定并且监听
    SOCKET hSocket = BindAnListen(1);
    if (INVALID_SOCKET == hSocket)
    {
        DebugLog(TEXT("main Bind Fail"));
        goto Opt;
    }
    // 2.循环接受套接字连接
    while (true)                            //主要代码是这里.
    {
        //接受客户端连接
        SOCKET hRetSocket = AccepeConnect(hSocket);

        if (INVALID_SOCKET == hRetSocket)
        {
            DebugLog(TEXT("main accept Fail"));
            break;
        }
        
        //读取数据.
        if (FALSE == ClientReadAnWriteData(hRetSocket))
        {
            //只服务一个socket.对其进行读取写入操作.然后下方进行关闭.

            break;
        }
        if (ColseConnect(hRetSocket))
        {
            break;
        }

    }

Opt:
    getchar(); //等待一下.观看错误内容
    ColseConnect(hSocket);

    return 0;
}

主要就是服务端的代码.客户端进行发送数据即可.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-09-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  •       网络编程基础第四讲阻塞模型
    • 一丶阻塞模型简介
      • 二丶阻塞模式迭代模式 与 并发连接模式
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档