添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

1.send 函数

int send( SOCKET s, const char FAR *buf, int len, int flags );

不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。
该函数的第一个参数指定发送端套接字描述符;
第二个参数指明一个存放应用程序要发送数据的缓冲区;
第三个参数指明实际要发送的数据的字节数;
第四个参数一般置0。 

这里只描述同步Socket的send函数的执行流程。当调用该函数时,

(1)send先比较待发送数据的长度len和套接字s的发送缓冲的长度, 如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;

(2)如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len

(3)如果len大于剩余空间大小,send就一直等待协议把s的发送缓冲中的数据发送完

(4)如果len小于剩余 空间大小,send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。

如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。

要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执 行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回 SOCKET_ERROR)

注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

通过测试发现,异步socket的send函数在网络刚刚断开时还能发送返回相应的字节数,同时使用select检测也是可写的,但是过几秒钟之后,再send就会出错了,返回-1。select也不能检测出可写了。

2. recv函数

int recv( SOCKET s, char FAR *buf, int len, int flags);

不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。该函数的第一个参数指定接收端套接字描述符;
第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
第三个参数指明buf的长度;
第四个参数一般置0。

这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,

(1)recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,

(2)如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以 在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),

recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。

注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

二、如何获取/修改默认缓冲区大小?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <assert.h> 
int main(int argc,char **argv) 
    int err = -1;        /* 返回值 */ 
    int s = -1;            /* socket描述符 */ 
    int snd_size = 0;   /* 发送缓冲区大小 */ 
    int rcv_size = 0;    /* 接收缓冲区大小 */ 
    socklen_t optlen;    /* 选项值长度 */ 
     * 建立一个TCP套接字 
    s = socket(PF_INET,SOCK_STREAM,0); 
    if( s == -1){ 
        printf("建立套接字错误\n"); 
        return -1;     
     * 先读取缓冲区设置的情况 
     * 获得 原始发送缓冲区大小 
    optlen = sizeof(snd_size); 
    err = getsockopt(s, SOL_SOCKET, SO_SNDBUF,&snd_size, &optlen); 
    if(err<0){ 
        printf("获取发送缓冲区大小错误\n"); 
     * 打印原始缓冲区设置情况 
     * 获得 原始接收缓冲区大小 
    optlen = sizeof(rcv_size); 
    err = getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 
    if(err<0){ 
        printf("获取接收缓冲区大小错误\n"); 
   printf(" 发送缓冲区原始大小为: %d 字节\n",snd_size); 
   printf(" 接收缓冲区原始大小为: %d 字节\n",rcv_size); 
     * 设置发送缓冲区大小 
    snd_size = 10*1024;    /* 发送缓冲区大小为8K */ 
    optlen = sizeof(snd_size); 
    err = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &snd_size, optlen); 
    if(err<0){ 
        printf("设置发送缓冲区大小错误\n"); 
     * 设置接收缓冲区大小 
    rcv_size = 10*1024;    /* 接收缓冲区大小为8K */ 
    optlen = sizeof(rcv_size); 
    err = setsockopt(s,SOL_SOCKET,SO_RCVBUF, (char *)&rcv_size, optlen); 
    if(err<0){ 
        printf("设置接收缓冲区大小错误\n"); 
     * 检查上述缓冲区设置的情况 
     * 获得修改后发送缓冲区大小 
    optlen = sizeof(snd_size); 
    err = getsockopt(s, SOL_SOCKET, SO_SNDBUF,&snd_size, &optlen); 
    if(err<0){ 
        printf("获取发送缓冲区大小错误\n"); 
     * 获得修改后接收缓冲区大小 
    optlen = sizeof(rcv_size); 
    err = getsockopt(s, SOL_SOCKET, SO_RCVBUF,(char *)&rcv_size, &optlen); 
    if(err<0){ 
        printf("获取接收缓冲区大小错误\n"); 
     * 打印结果 
    printf(" 发送缓冲区大小为: %d 字节\n",snd_size); 
    printf(" 接收缓冲区大小为: %d 字节\n",rcv_size); 
    close(s); 
    return 0; 

执行结果(QNX系统中):
在这里插入图片描述

一、send/recv详解1.send 函数int send( SOCKET s, const char FAR *buf, int len, int flags );不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。该函数的第一个参数指定发送端套接字描述符;第二个参数指明一个存放应用程序要发送数据的缓冲区;第三个参数指明实际要发送的数据的字节数;第四个参数一般置0。
int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。 客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。 该函数的第一个参数指定发送端套接字描述符; 第二个参数指明一个存放应用程序要发送数据的缓冲区; 第三个参数指明实际要发送的数据的字节数; 第四个参数一般置0。 这里只描述同步Socketsend函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲的 长度, 如果
前几天用PHP写一个socket网络服务,在文档里看到socket_read和socket_recv这两个方法时有点晕,乍一看这不是一样的嘛,干吗还要给两个不同的用法呢。看文档没看太明白,看了下源码才搞清楚,在这里记录一下。 先看一下这两个函数的声明: 复制代码 代码如下: string socket_read ( resource $socket , int $length [, int $type = PHP_BINARY_READ ] ) int socket_recv ( resource $socket , string &$buf , int $len , int $flags )
今天想分享一些socket编程的例子,socket嵌入式。linux开发很常用,用于进程间通信很方便,也有很多介绍,今天我也也来做自己的介绍分享。和别人不一样的地方,我主要想分享socket 服务端在linux写的代码,使用vscode调试执行,并且同时分享自己使用tcp监控软件去判断socket通信正确性。
先说明一下粘包的概念: 发送时是两个单独的包、两次发送,但接收时两个包连在一起被一次接收到。 在以前 WinCE 下 Socket 编程,确实也要处理粘包的问题,没想到在 Android 下也遇到了。 首先想从发送端能否避免这样的问题,例如: (1) 调用强制刷数据完成发送的函数;(2) 设置发送超时。 1 先试了调用 flush() 函数,但运行后现象依旧 2 设置发送超时是 Windows 平台的做法,但在 Android 平台下是否有类似的设置呢? 查看 Socket 类的实现代码:java.net.
服务端在ubuntu服务器下,客户端在windows下,采用socket进行通信,在客户端接收数据时,出现了诡异的情况,recv返回值大于0,但缓冲区大小为0,代码如下:char buff[10]; int res=recv(ClientSocket, buff, 10, 0); cout << res << endl;//返回8,表示有接收到数据 cout << strlen(buff) << e
客户端并没有send,服务端会继续调用recv函数(而不是被阻塞),接收到一大片的空字符缓冲 发现好像是服务器的缓冲区大小大于客户端的,所以会调用recv函数2次 其实看到百度百科中对recv这个函数的解释中说到:
UDP收发缓冲区大小可以通过操作系统提供的相关函数来获取。在Linux系统中,可以使用getsockopt函数来获取UDP套接字的缓冲区大小。具体的代码实现如下: int sockfd = socket(AF_INET, SOCK_DGRAM, 0); int recv_buf_size, send_buf_size; socklen_t len; // 获取接收缓冲区大小 len = sizeof(recv_buf_size); getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recv_buf_size, &len); // 获取发送缓冲区大小 len = sizeof(send_buf_size); getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &send_buf_size, &len); printf("Receive buffer size: %d\n", recv_buf_size); printf("Send buffer size: %d\n", send_buf_size); 在Windows系统中,可以使用getsockopt函数获取UDP套接字的缓冲区大小。具体代码实现如下: SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, 0); int recv_buf_size, send_buf_size; int len; // 获取接收缓冲区大小 len = sizeof(recv_buf_size); getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char*)&recv_buf_size, &len); // 获取发送缓冲区大小 len = sizeof(send_buf_size); getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char*)&send_buf_size, &len); printf("Receive buffer size: %d\n", recv_buf_size); printf("Send buffer size: %d\n", send_buf_size); 云深n不知处: [root@localhost lib]# umount /var/lib/docker/aufs umount: /var/lib/docker/aufs: mountpoint not found [root@localhost lib]# umount /var/lib/docker umount: /var/lib/docker: mountpoint not found