socket编程:recv()函数详解

文章目录

1. 函数原型2. 函数使用3. 参数详解4. 返回值

官方文档:https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recv

1. 函数原型

recv函数从连接的套接字或绑定的无连接套接字接收数据。

int WSAAPI recv(

SOCKET s,//标识已连接套接字的描述符。

char *buf,//指向缓冲区的指针,以接收传入的数据。

int len,//buf参数指向的缓冲区的长度(以字节为单位)。

int flags//一组影响此功能行为的标志。

);

**本质:**复制

数据的接收都是由协议本身做的,也就是socket的底层做的,系统会有一段缓冲区,存储着接收到的数据。咱们外边调用recv的作用,就是通过socket找到这个缓冲区,并把数据复制到咱们的参数2指向的地址,复制参数3个。

2. 函数使用

#define WIN32_LEAN_AND_MEAN

#include

#include

#include

// Link with ws2_32.lib

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

#define DEFAULT_BUFLEN 512

#define DEFAULT_PORT "27015"

int __cdecl main() {

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

// Declare and initialize variables.

WSADATA wsaData;

int iResult;

SOCKET ConnectSocket = INVALID_SOCKET;

struct sockaddr_in clientService;

char *sendbuf = "this is a test";

char recvbuf[DEFAULT_BUFLEN];

int recvbuflen = DEFAULT_BUFLEN;

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

// Initialize Winsock

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

if (iResult != NO_ERROR) {

printf("WSAStartup failed: %d\n", iResult);

return 1;

}

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

// Create a SOCKET for connecting to server

ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (ConnectSocket == INVALID_SOCKET) {

printf("Error at socket(): %ld\n", WSAGetLastError() );

WSACleanup();

return 1;

}

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

// The sockaddr_in structure specifies the address family,

// IP address, and port of the server to be connected to.

clientService.sin_family = AF_INET;

clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );

clientService.sin_port = htons( 27015 );

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

// Connect to server.

iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );

if ( iResult == SOCKET_ERROR) {

closesocket (ConnectSocket);

printf("Unable to connect to server: %ld\n", WSAGetLastError());

WSACleanup();

return 1;

}

// Send an initial buffer

iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );

if (iResult == SOCKET_ERROR) {

printf("send failed: %d\n", WSAGetLastError());

closesocket(ConnectSocket);

WSACleanup();

return 1;

}

printf("Bytes Sent: %ld\n", iResult);

// shutdown the connection since no more data will be sent

iResult = shutdown(ConnectSocket, SD_SEND);

if (iResult == SOCKET_ERROR) {

printf("shutdown failed: %d\n", WSAGetLastError());

closesocket(ConnectSocket);

WSACleanup();

return 1;

}

// Receive until the peer closes the connection

do {

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

if ( iResult > 0 )

printf("Bytes received: %d\n", iResult);

else if ( iResult == 0 )

printf("Connection closed\n");

else

printf("recv failed: %d\n", WSAGetLastError());

} while( iResult > 0 );

// cleanup

closesocket(ConnectSocket);

WSACleanup();

return 0;

}

3. 参数详解

s

客户端或服务端的socket,每个客户端对应唯一的socket buf

客户端消息的存储空间,也就是个字符数组一般为1500字节

网络传输的最大单元,1500字节,也就是客户端发过来的数据,一次最大就是1500字节,这是协议规定,这个数值也是根据很多情况,总结出来的最优值所以客户端最多一组来1500字节,咱们这头1500读一次,就够了。 len

想要读取到字节个数,一般是参数2的字节数-1,把\0字符串结尾留出来 flags

一般设置为0

MSG_PEEK:窥视传入的数据。 数据被复制到缓冲区中,但不会从输入队列中删除。

MSG_OOB:处理带外(OOB)数据。

MSG_WAITALL:

仅当发生以下事件之一时,接收请求才会完成:

调用方提供的缓冲区已完全满。连接已关闭。该请求已被取消或发生错误。

4. 返回值

读出来的字节大小

读没了咋办?

在recv函数卡着,等着客户端发来数据(即阻塞、同步)阻塞的 客户端下线,返回0

释放客户端socket 执行失败,返回SOCKET_ERROR

WSAGetLastError() 得到错误码根据错误码信息做相应处理

重启等待不用理会

热门