《ASCE1885的网络编程》---Winsock APIの套接口I/O处理函数

TCP/IP网络编程期末考试复习 第一章 1、Internet是以 ARPANET 网络为雏形建立的 2、现在Internet中广泛使用的   TCP/IP  协议族,其版本为  V4 3、tcp/ip一般分为  网络接口层 , 网际层  , 传输层  和  应用层  四层 4、常用的http工作在tcp./ip的 应用层  层 5、ip地址属于tcp/ip中 网际层  的概念 6、传输层常用的两个协议是 阅读详情

在Windows环境下,套接口的通信方式分为两种:阻塞方式和非阻塞方式。阻塞方式下工作的套接口在进行I/O操作时,函数要等待到相关操作完成以后才能返回;非阻塞方式下工作的套接口在进行I/O操作时,无论操作是否成功,调用都会立即返回。

阻塞方式和非阻塞方式各有优缺点,阻塞方式的套接口编程简单,易于实现。因此,一个套接口默认操作模式被设置为阻塞方式。如果要使套接口工作在非阻塞方式下,就要使用ioctlsocket()函数进行设置。阻塞方式的套接口在下面几种情况下显得难于管理:

1)当有多个已建立连接的套接口需要进行管理的;

2)当发送的数据量不均匀或接收的数据量不均匀时;

3)当发送或接收的数据时间不确定时。

在进行程序设计时,应该尽量使用非阻塞方式的操作,但非阻塞方式的套接口较为复杂,并且由于操作常常失败,因此在程序中就要考虑操作失败时应该如何处理了。、

 

1)设置套接口的工作方式---ioctlsocket()和WSAIoctl():

int ioctlsocket(

  __in     SOCKET s, //套接字描述字

  __in     long cmd, //预定义好的标志,表示对套接口s的操作控制命令

  __inout  u_long *argp //指向cmd命令所待参数的指针

);

 

在Winsock2中引入一个新的功能更强大的函数是WSAIoctl():

int WSAIoctl(

  __in   SOCKET s, //套接字描述字

  __in   DWORD dwIoControlCode, //指示将要进行的操作的控制代码

  __in   LPVOID lpvInBuffer, //指向函数的输入参数(用于描述函数输入参数缓冲区的地址)

  __in   DWORD cbInBuffer, //用于描述输入缓冲区的大小

  __out  LPVOID lpvOutBuffer, //指向函数的返回参数(用于描述函数返回数据缓冲区的地址)

  __in   DWORD cbOutBuffer, //用于描述返回参数缓冲区的大小

  __out  LPDWORD lpcbBytesReturned, //指向函数实际返回的字节数的地址

  __in   LPWSAOVERLAPPED lpOverlapped, //WSAOVERLAPPED结构的地址

  __in   LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine //一个指向操作结束后

                                     //调用的例程指针,该参数和lpOverlapped使用在重叠I/O中

);

 

Ioctlsocket()和WSAIoctl()函数支持的标准I/O命令有FIONBIO、FIONREAD和SIOCATMARK:

1)FIONBIO:该命令用于在套接口s上允许或禁止非阻塞模式。一个套接口在创建好以后,默认的通信模式是阻塞模式,如果要在程序中对一个创建好的套接口通行模式进行设置,那么ioctlsocket()函数的第二个参数使用命令FIONBIO,第三个参数argp设为0时,表示禁止非阻塞模式;设为非0值,表示允许非阻塞模式。

要注意:如果使用WSAAsyncSelect()函数或WSAEventSelect()函数,则套接口将会自动设置为非阻塞模式。如果已对一个套接口进行了WSAAsyncSelect()操作,则任何用ioctlsocket()调用来套接口重新设置成阻塞模式的操作都将失败,并返回WSAEINVAL错误。为了把套接口重新设置成阻塞模式,应用程序必须把IEvent参数置为0,调用WSAAsyncSelect()函数,以禁止WSAAsyncSelect()调用;或者令INetworkEvents参数等于0,调用WSAEventSelect()函数,从而禁止WSAEventSelect()。

 

2)FIONREAD:该命令用于确定可从套接口s上自动读入的数据量。参数argp指向一个无符号长整型量,其中存有打算读入的字节数。如果使用WSAIoctl()函数,那么无符号整数是通过lpvOutBuffer返回的。如果套接口s面向数据流(SOCK_STREAM类型)的套接口,则FIONREAD返回一次recv()调用中所接收的数据总量,这通常与套接口中排队的数据总量相同;如果套接口s是面向数据报(SOCK_DGRAM类型)的套接口,则FIONREAD返回套接口上排队的第一个数据报的大小。

 

3)SIOCATMARK:该命令用于确定是否所有的带外数据都已被读入。这个命令仅适用于SOCK_STREAM类型的套接口,且该套接口已被设置为可以在线接收带外数据(SO_OOBINLINE)。如无带外数据等待读入,则该操作返回TRUE,否则返回FALSE,下一个recv()或revcfrom()操作将检索“标记”前的一些或所有数据。应用程序可用SIOCATMARK操作来确定是否有数据剩余。如果在“紧急”带外数据前有常规数据,则按序接收这些数据(注意:recv()和recvfrom()操作不会在一次调用中混淆常规数据和带外数据)。

对于ioctlsocket()函数来说,argp指向一个BOOL值,在其中存入返回值;而对于WSAIoctl()函数来说,会在lpvOutBuffer中返回指向布尔变量的指针。

 

Ioctlsocket函数使用实例如下:

//-------------------------

// Initialize Winsock

WSAData wsaData;

int iResult = WSAStartup(NAKEWORD(2,2), &wsaData);

if(iResult != NO_ERROR)

    printf("Error at WSAStartup/n");

 

//-------------------------

// Create a SOCKET object.

SOCKET m_socket;

m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if(m_socket == INVALID_SOCKET)

{

    printf("Error at socket():%d/n", WSAGetLastError());

    WSACleanup();

    return;           

}

 

//-------------------------

// Set the socket I/O mode: In this case FIONBIO

// enables or disables the blocking mode for the

// socket based on the numerical value of iMode.

// If iMode = 0, blocking is enabled;

// If iMode != 0, non-blocking mode is enabled.

u_long iMode = 0;

ioctlsocket(m_socket, FIONBIO, &iMode);

 

2)套接口I/O状态查询---select()

使用select()函数的好处是在进行I/O操作之前,可以首先判断能否向一个套接口写入数据,或者套接口上是否存在可读的数据。这样就可以防止应用程序在套接口处于阻塞模式时,对它进行的I/O操作被迫进入等待状态;同时也可以防止在套接口处于非阻塞模式时,产生WSAEWOULDBLOCK错误。

select函数原型如下:

int select(

  __in     int nfds, //本参数被忽略,仅起到与Berkeley API套接口兼容的作用

  __inout  fd_set *readfds, //检查可读性

  __inout  fd_set *writefds, //检查可写性

  __inout  fd_set *exceptfds, //检查例外数据

  __in     const struct timeval *timeout //本次select()调用最长等待时间

);

 

fd_set是一个结构类型说明符,代表这一系列特定套接口的集合:

typedef struct fd_set {

  u_int  fd_count; //套接口的数目

  SOCKET fd_array[FD_SETSIZE]; //表示数组中存放的套接口号,FD_SETSIZE是常量,定义为64

} fd_set;

 

timeval是一个结构类型,定义如下:

typedef struct timeval {

  long tv_sec; //等待的秒数

  long tv_usec; //等待的毫秒数

} timeval;

tv_sec和tv_usec字段都表示等待时间,只是单位不同。它们的设置可分为如下三种情况:

1)如果在调用select()函数时将等待时间tv_sec和tv_usec都设置为0,则select()调用在检查完套接口描述符后立即返回,这可用于探询所选套接口的状态。如果处于这种状态,则select()调用可认为是非阻塞的。

2)如果在调用select()函数时将timeout指向NULL,则进行阻塞等待,即被监视的描述符中只有当其中的任何一个准备好读写操作时,select()调用才返回。

3)如果等待时间tv_sec和tv_usec不全为0,则当等待时间没有超时时,select()函数在被检查的描述符中有任何一个套接口准备好读写时返回。

 

select()函数可用于检查一个或多个套接口的状态。对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息。用fd_set结构来表示一组等待检查的套接口,在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select返回满足条件的套接口数目。

为了方便对readfds、writefds和exceptfds集合进行操作,Winsock实现中已经定义好了如下4个宏,以简化程序的设计:

1)FD_SET(s, *set):向set集合添加套接口描述符s;

2)FD_CLR(s, *set):从set集合中删除套接口描述符s;

3)FD_ISSET(s, *set):检查s是否为set集合的一员,如果是则返回TRUE;

4)FD_ZERO(*set):将set集合初始化为空集;

 

这样使用select函数对一个或多个套接口进行检查的过程如下:

1)使用FD_ZERO宏,初始化要检查的每一个集合;

2)使用FS_SET宏,将要检查的套接口加入到一个集合中;

3)设置等待时间,即对timeval中的tv_sec和tv_usec字段进行设置;

4)调用select函数;

5)当select函数正确返回时,使用FD_ISSET检查一个选定的套接口是否在指定的集合中。

 

具体在程序中使用select函数时,还要注意以下几个问题:

1)readfds参数中包括的套接口标识符<有可读入数据的套接口>,<正处于监听listen()状态且有连接请求到达的套接口>,<已经关闭、重设或终止的套接口>。

2)writefds参数中包括的套接口标识符有<可写的套接口>。如果一个套接口正在connect()连接(非阻塞),则可写性意味这连接顺利建立。

3)exceptfds参数中包括的套接口标识符有<带外数据可读>。假如已完成对一个非阻塞连接调用的处理,连接尝试就会失败。注意:如果设置了SO_OOBINLINE选项为FALSE,则只能用这种方法来检查带外数据的存在与否。   对于SO_STREAM类型的套接口,远端造成的连接中止和KEEPALIVE错误都将被作为例外出错。   如果套接口正在进行连接connect()(非阻塞方式),则连接试图的失败将会表现在exceptfds中。

4)如果不想对readfds、writefds和exceptfds进行监视,则可将其值为NULL,但三组参数不能同时全为NULL。

 

select()函数使用实例,从网络上接收数据:

#include <winsock2.h>

#include <stdio.h>

#include <windows.h>

 

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

 

#define PORT 5150

#define MSGSIZE 1024

 

int g_iTotalConn = 0;

SOCKET g_socketArr[FD_SETSIZE];

 

DWORD WINAPI WorkerThread(LPVOID lpParam);

 

int main()

{

    WSADATA wsaData;

    SOCKET listenSock, clientSock;

    sockaddr_in localAddr, clientAddr;

   

    int iaddrsize = sizeof(sockaddr_in);

    DWORD dwThreadId;

   

    //Initialize Windows socket library

    WSAStartup(MAKEWORD(2,2), &wsaData);

    //Create listening socket

    listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   

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

    localAddr.sin_family = AF_INET;

    localAddr.sin_port = htons(PORT);

   

    bind(listenSock, (struct sockaddr*)&localAddr, sizeof(sockaddr_in));

   

    //Create Worker Thread

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

    while(TRUE)

    {

        clientSock = accept(listenSock, (struct sockaddr*)&clientAddr, &iaddrsize);

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

        //Add socket to g_socketArr

        g_socketArr[g_iTotalConn++] = clientSock;

    }

   

    system("pause");

    return 0;   

}

 

//Thread function

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_socketArr[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_socketArr[i], &fdread))

            {

                //A read event happened on g_socketArr

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

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

                {

                    //Client socket closed

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

                    closesocket(g_socketArr[i]);      

                    if(i < g_iTotalConn - 1)

                    {

                        g_socketArr[i--] = g_socketArr[--g_iTotalConn];    

                    }

                }                        

                else

                {

                    //We received a message from client

                    szMessage[ret] = '/0';

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

                }

            }       

        }

    }

    return 0;

}

 

3)异步事件通知---WSAAsyncSelect()

WSAAsyncSelect()是Winsock提供的一个适合于Windows编程使用的函数,它允许在一个套接口上当发生特定的网络事件时,给Windows网络应用程序(窗口或对话框)发送一个消息(事件通知):

int WSAAsyncSelect(

  __in  SOCKET s, //标识一个需要事件通知的套接口描述符

  __in  HWND hWnd, //标识一个在网络事件发生时要想收到消息的窗口或对话框的句柄

  __in  unsigned int wMsg, //在网络事件发生时要接收的消息,该消息会投递到由hWnd句柄指定

                            //的窗口或对话框

  __in  long lEvent //位屏蔽码,用于指明应用程序感兴趣的网络事件集合

);

WSAAsyncSelect函数常用到的网络事件:

 

若应用程序感兴趣的网络事件声明成功,则返回0;如果声明失败,则返回SOCKET_ERROR错误信息。可进一步调用WASGetLastError()函数返回如下的特定错误代码:

WSANOTINITIALISED  //在使用本API之前必须进行一次成功的WSAStartup()调用

WSAENETDOWN //Windows Sockets实现已检测到网络子系统故障

WSAENIVAL   //指定的参数之一是非法的

WSAEINPROGRESS       //一个阻塞的Windows Sockets操作正在进行

 

附加的错误代码可能在应用程序窗口接收到消息时被设置,这些代码可以用WSAGETSELECTERROR宏从lParam中取出,对应于每个网络事件的可能错误代码说明如下:

1)网络事件FD_CONNECT可能的错误代码:

WSAEADDRINUSE         //给定的地址已被使用

WSAEADDRNOTAVAIL        //指定的地址在本地机器不能使用

WSAEAFNOSUPPORT //指定族的地址不能和本套接口同时使用

WSAECONNREFUSED //连接的尝试被拒绝

WSAEDESTADDRREQ  //需要一个目的地址

WSAEFAULT  //namelen参数不正确

WSAEINVAL   //套接口已经约束到一个地址

WSAEISCONN        //套接口已经连接

WSAEMFILE   //没有可用的文件描述符

WSAENETUNREACH    //此时网络不能从该主机访问

WSAENOBUFS       //无可用的缓冲区空间,套接口不能连接

WSAENOTCONN //套接口没有连接

WSAENOTSOCK   //该描述符是文件,不是套接口

WSAETIMEOUT    //试图连接超时,未建立连接

 

2)网络事件FD_CLOSE可能的错误代码是:

WSAENETDOWN //Windows Sockets实现已检测到网络子系统故障

WSAECONNRESET        //连接由远端重建

WSAECONNABORTED         //由于超时或其他失败放弃连接

 

3)网络事件FD_READ、FD_WRITE、FD_OOB和FD_ACCEPT可能的错误代码为:

WSAENETDOWN //Windows Sockets实现已检测到网络子系统故障

 

WSAAsyncSelect函数用来请求Windows Sockets DLL为窗口句柄发送一条由IEvent参数指明的网络事件。要发送的消息由wMsg参数表明,在使用时要注意以下问题:

1)若应用程序对一个套接口s调用了WSAAsyncSelect()函数,那么套接口s的模式会自动从阻塞模式变成非阻塞模式。这样一来,假如在程序中调用了像WSARecv()这样的I/O函数,当没有数据可用时,必然会造成调用失败,并返回WSAEWOULDBLOCK错误信息;

2)如果应用程序同时对多个网络事件感兴趣,那么只需对各种类型的网络事件执行按位或的运算即可。例如,当一个网络应用程序对套接口s上的连接、发送以及套接口关闭这三个网络事件感星期时,可以用如下的格式调用WSAAsyncSelect函数:

rc = WSAAsyncSelect(s, hWnd, wMsg, FD_CONNECT | FD_WRITE | FD_CLOSE);

3)特别要注意的是,进行一次WSAAsyncSelect()调用,将使为同一个套接口启动的所有以前的WSAAsyncSelect()调用作废。例如,要接收读写通知,应用程序必须同时用FD_READ和FD_WRITE调用WSAAsyncSelect():

rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ | FD_WRITE);

而不能使用如下的调用方式,因为第二次调用将使第一次调用的作用失效:

rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ);

rc = WSAAsyncSelect(s, hWnd, wMsg, FD_WRITE);

4)如果要取消所有的通知,也就是指出Windows Sockets的实现不再在套接口上发送任何和网络事件相关的消息,则把IEvent字段置为0,然后调用WSAAsyncSelect()即可:

rc = WSAAsyncSelect(s, hWnd, 0 , 0);

尽管在本例中,WSAAsyncSelect()调用立即使传给该套接口的事件消息无效,但仍可能有消息等待在应用程序的消息队列中,应用程序因此也必须仍准备好接收网络消息(即使消息作废)。用closesocket()关闭一个套接口也同样使WSAAsyncSelect()发送的消息作废,但在调用closesocket()之前,队列中的消息仍然起作用。

5)当某一套接口s上发生了一个已命名的网络事件时,应用程序窗口hWnd会接收到消息wMsg。应用程序窗口例程的wParam参数标识了网络事件发生的套接口,lParam参数的低位字指明了发生的网络事件,高位字则含有一个错误代码。错误代码和事件可以通过WSAGETSELECTERROR和WSAGETSELECTEVENT宏从lParam中取出,宏定义如下:

#include <windows.h>

#define WSAGETSELECTEVENT(lParam)       LOWORD(lParam)

#define WSAGETSELECTERROR(lParam)       HIWORD(lParam)

若应用程序发现套接口上没有产生任何错误,接着便会检查lParam的低位字,以弄清到底是哪个网络事件类型造成了这条Windows消息的触发。

 

4)取消正在执行的阻塞调用---WSACancelBlockingCall()

如果应用程序中想取消正在执行的阻塞调用,就要使用WSACancelBlockingCall()函数。要注意的是,在Winsock2的实现规范中已经不包括该函数了:

int WSACancelBlockingCall(void);

 

5)判断是否有阻塞调用---WSAIsBlocking()

该函数用于判断是否有阻塞调用正在进行:

BOOL WSAIsBlocking(void);

如果存在一个尚未完成的阻塞函数在等待完成,则函数返回TRUE,否则返回FALSE。

在Winsock2的实现规范中已经不包括该函数了,在Winsock1.1中使用该函数时要注意它禁止对每一个线程多于一个未完成的调用。

 

6)取消一个未完成的异步操作---WSACancelAsyncRequest()

int WSACancelAsyncRequest(

  __in  HANDLE hAsyncTaskHandle //指明将要被取消的异步操作

);

如果该操作成功地取消了异步操作,则函数返回0,否则返回SOCKET_ERROR错误信息。可通过WSAGetLastError()调用获得对错误的进一步描述,错误代码如下:

WSANOTINITIALISED  //在使用本API前必须进行一次成功的WSAStartup()调用

WSAENETDOWN //Windows Sockets实现已检测到网络子系统故障

WSAEINVAL   //指示异步操作句柄非法

WSAEINPROGRESS       //一个阻塞的Windows Sockets操作正在进行

WSAEALREADY      //被取消的异步操作已经完成

 

WSACancelAsyncRequest()函数用于取消一次异步操作,该异步操作应该是以一个WSAAsyncGetXByY()函数的形式(例如WSAAsyncGetHostByName())启动的。hAsyncTaskHandle参数标识了要取消的操作,它应由初始函数作为异步任务句柄返回。

试图取消一个已存在的异步操作WSAAsyncGetXByY()可能失败(错误代码是WSAEALREADY),这有两种原因:一是原来的操作已经完成,并且应用程序已经处理了结果消息;二是原来的错误已经完成,但结果消息仍在应用程序窗口队列中等待。

 

 

 

 

嵌入式充电协议深度解析:从QC到PD3.1的技术演进与实战应用 本文深入解析了从QC到PD3.1的嵌入式充电协议技术演进与实战应用。通过电压谈判、协议芯片设计、Type-C接口优化等关键技术,详细介绍了快充协议在嵌入式系统中的实现挑战与解决方案,包括兼容性测试、EMC问题处理及空间限制创新设计,为开发者提供了宝贵的实践经验。 阅读详情

相关推荐

支付漏洞防护绕过的一种方式

放完包后就到了提交订单的地方,可以发现,金额确实小了很多,合理的搭配的话还可以更低,再次前进可以发现,金额确实是这么多,后面就不支付了,到此就结束了。也就是说数量可以为负数,但是金额不能为0或者0以下,有什么方法可以绕过这个限制吗,其实并不难,既然可以为负数,只是对金额不能为0或者负数做了限制。我们可以尝试拼接法,利用负数加上正数让他的值变得很低,但是又大于0就可以了,这里利用购物车的结算方法,随机加一些在购物车里。这里为了方便查看数据包,我这边商品的数量选择3,点击立即购买并抓包。

2301_80115097的博客 1528

c语言网络编程(1)ocket之Winsock API

原文地址:https://www.cnblogs.com/hitWTJ/p/9886700.html 我搬家到博客园了。。。 参考网址:https://blog.youkuaiyun.com/Datura_Metel/article/details/79900395 https://www.2cto.com/kf/201804/736240.html https://blog.youkuaiyun.com/m0_379...

清凌的博客 993

【Telephony】APN配置及加载流程&项目实践(AOSP)

学习APN关键是学会明白apns-conf.xml文件各个参数的意思,然后熟悉TelephonyProvider是如何读取文件创建数据库的,譬如数据库表的约束、文件的读写顺序等,还有读取后的ApnSetting的二次定制以及显示(例如屏蔽xcap等)。虽然一般在项目中APN的需求很简单,就是按照客户提供的APN参数添加上配置,或者在显示屏蔽一些参数,但是项目维护的过程中APN的问题也是比较多的。

weixin_44513784的博客 5509

Winsock 网络编程 Socket模型之WSAAsyncSelect模型

前言: 讲一下套接字模式和套接字I/O模型的区别。先说明一下,只针对Winsock 套接字模式:阻塞套接字和非阻塞套接字。或是叫同步套接字和异步套接字。 套接字模型:描述如何对套接字的I/O行为进行管理 Winsock提供的I/O模式一共有五种: Select模型,WSAAsyncSelect模型,WSAEventSelect模型,Overlapped模型(重叠IO),Compl

未来取款机 730

从零到一:YT8512C PHY芯片在STM32F407上的LWIP移植实战与避坑指南

本文详细介绍了YT8512C PHY芯片在STM32F407平台上基于LWIP协议栈的移植实战,涵盖硬件连接、CubeMX配置、寄存器定制和调试技巧。重点解析了与主流PHY芯片的差异,提供了完整的避坑指南和优化建议,帮助开发者快速实现稳定可靠的嵌入式网络连接。

uber9的博客 538

Axure RP 9在Windows 11环境下的高效安装与配置指南

本文提供Axure RP 9在Windows 11系统下的详细安装步骤与配置指南。针对Win11安全特性,从获取官方安装资源、调整系统权限,到定制化安装路径、精准汉化及性能优化,系统性地解决了安装闪退、汉化失败、运行卡顿等常见问题,确保用户获得稳定流畅的原型设计体验。

mango的博客 480

网络编程---socket中关闭套接字的函数close和shutdown区别

1.函数close():释放描述符 某个进程调用了close(sockfd)函数,描述符的计数就会减1,直到计数为0。当计数为0时,也就是所用进程都调用了close,这时程序会调用shutdown函数释放套接字。 2.函数shutdown():断开连接 有些地方见到调用了shutdown()之后接着就是close()。有种解释是:调用shutdown()只是进行了TCP断开, 并没有释放文件描述符,需要调用close()来释放。 某个进程中调用了shutdown(sockfd,SHUT_RDWR)函数,其

m0_46598535的博客 6075

yolov5直接调用zed相机实现三维测距(python)

zed代码比较简洁,但是一定要把环境配置好,后续自己会把他当做普通双目标定,去对比分析效果,并完善相关功能。

积极向上的mr.d的博客 1万+

《ASCE1885的网络编程》---Winsock APIのIP地址转换函数

在进行网络程序设计时,常常需要从键盘上输入用点分十进制记法表示的主机IP地址,这种IP地址在程序中一般是用ASCII字符串的形式存储的。在网络程序中,要把这种用点分十进制字符串表示的IP地址转换为用网络字节顺序表示的IP地址。如果在程序中需要输出IP地址时,要把用二进制表示的网络字节顺序的IP地址转化为点分十进制形式表示的主机IP地址,用户才可以识别。在Winsock API中提供了这样的函数,这种函数以inet开头。1)点分十进制表示的IP地址转换为网络字节顺序的IP地址---inet_addr()Ine

ASCE1885 2417

EtherCAT主站SOEM -- 18 --Qt-Soem通过CSV模式(周期同步速度模式)控制一个电机转圈圈

以上就是 EtherCAT主站SOEM – 18 --Qt-Soem通过CSV模式(周期同步速度模式)控制一个电机转圈圈 的内容。有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。创作不容,如果文档对您有帮助,记得给个赞。

常驻客栈的博客--嵌入式EtherCAT 1211

2025年华为杯中国研究生数学建模竞赛C题 围岩裂隙精准识别与三维模型重构 思路+代码

report += f"**位置 {i+1}**: ({loc[0]:.1f}, {loc[1]:.1f}, {loc[2]:.1f})\n"# ==================== 高级U-Net模型 ====================# ==================== 数据预处理与增强 ====================# ==================== 采样方法比较分析 ====================

YOLO 1527

《ASCE1885的网络编程》---IP数据报格式

IP协议提供不可靠无连接的数据报传输服务,IP层提供的服务是通过IP层对数据报的封装与拆封来实现的。IP数据报的格式分为报头区和数据区两大部分,其中报头区是为了正确传输高层数据而加的各种控制信息,数据区包括高层协议需要传输的数据。IP数据报的格式如下:注意,上图表示的数据,最高位在左边,记为0位;最低位在右边,记为31位。在网络中传输数据时,先传输0~7位,其次是8~15位,然后传输16~23位,最后传输24~31位。由于TCP/IP协议头部中所有的二进制数在网络中传输时都要求以这种顺序进行,因此把它称为网

ASCE1885 2248

Qt和FFmpeg的视频压缩工具

m_progressDialog = new QProgressDialog("正在压缩视频...", "取消", 0, 100, parent);QString file = QFileDialog::getOpenFileName(this, "选择视频文件", "",QString file = QFileDialog::getSaveFileName(this, "保存压缩文件", "",QMessageBox::warning(parent, "错误", "请设置输入和输出文件路径");

寒寒豆豆软件公司的博客 102

《ASCE1885的网络编程》の套接字select模型

套接字Select模型使得Windows Sockets应用程序可以在同一时间内管理和控制多个套接字。该模型的核心是select()函数,在使用该函数时,还需要用到FD_SET、FD_ZERO、FD_ISSET和FD_CLR四个宏。 套接字的select模型,能够使得Windows Sockets应用程序同时对多个套接字进行管理。调用select()函数检查当前各个套接字的当前状态。并且根据该函

ASCE1885 2133

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

《ASCE1885的网络编程》---地址解析协议

<br />TCP/IP协议族分为四层,其中在数据链路层传输的数据帧只能识别网卡物理地址,常用的以太网就是48位的MAC地址。TCP/IP协议族专门设计了用于地址解析的协议ARP(Address Resolution Protocol),它可以把一个IP地址映射成对应的物理地址。另外,对于无法保存IP地址的主机(如无盘工作站),TCP/IP协议族也提供了从物理地址到IP地址映射的反向地址解析协议RARP(Reverse Address Resolution Protocol):<br /><br /><br

ASCE1885 1877

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

《ASCE1885的网络编程》の以太网接口堆栈

网络工作在通信协议上,现在非常普遍的是使用TCP/IP的以太局域网(Ethernet LAN)。在局域网中,计算机可以用同轴电缆、双绞线或光纤连接起来。现在大多数网络使用双绞线连接。以太网包含以下几层:1)介质访问控制(MAC)层以太网的最底层是硬件层,称为介质访问控制(Media Access Control)层。网卡属于该层,它包含了串行网络接口和一个控制器,控制器将原始数据转换成电子信号,并发送到正确位置。以太网接口的各层有不同的寻址方法,在最下面的MAC层,寻址是通过MAC号进行的。MAC号是一个4

ASCE1885 1832

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

《ASCE1885的网络编程》---Winsock API基本函数の数据传输

<br />在Winsock中,用于数据发送和接收的系统调用分为两组:一组是有连接的数据发送和接收系统调用;一组是无连接的数据发送和接收系统调用。这里我们先弄清与数据发送和接收关系密切的“带外数据”的概念。<br /> <br />1)带外数据概念:<br /> <br />有时我们可能要传输一些相对来说比较重要的数据,如果按普通数据进行传送,那么在传输过程中要受流量、拥挤等控制的影响。对于这些比普通数据重要的数据,在传输过程中可以标记为带外数据(Out-Of-Band,OOB)。<br />对于带外数据,

ASCE1885 1830

《ASCE1885的网络编程》---Winsock APIの网络信息获取函数

<br />网络中的主机需要安装TCP/IP协议或其他协议才能进行通信,网络应用程序有时需要获取主机上或网络有关的信息,这些信息一般存放在数据文件中。如Unix系统中,主机名存放在/etc/hosts文件中,网络信息则存放在etc/networks文件中,因此这类获取主机上与网络有关的信息的函数也叫数据库函数。<br />与网络有关的信息主要分为4大类:<br />主机信息:函数名一般以gethostby开头,在程序中较多使用;<br />网络信息:函数名一般以getnetby开头,在程序中较少使用;<br

ASCE1885 1768

《ASCE1885的网络编程》---Windows API基本函数の套接口与连接的建立

<br />1)打开Winsock---WSAStartup()<br />使用Winsock API编制的网络应用程序中,在调用任何一个Winsock函数之前,都必须检查协议栈的安装情况,也就是检查系统中是否有Windows Sockets的实现库。调用的是WSAStartup函数,详见:《Windows API巡礼》---WSAStartup和WSACleanup(http://blog.youkuaiyun.com/ACE1985/archive/2010/07/03/5710430.aspx)。<br /> <

ASCE1885 1751
上一篇: 《ASCE1885的网络编程》---Winsock APIの套接口选项函数
下一篇: 《ASCE1885的网络编程》---Winsock API基本函数の数据传输
ACE1985
博客等级 码龄17年 1307粉丝 308原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值