socket读写

TCP协议是面向流的,read和write调用的返回值往往小于参数指定的字节数。对于read调用,如果接收缓冲区中有20字节,请求读100个字节,就会返回20。对于write调用,如果请求写100个字节,而发送缓冲区中只有20个字节的空闲位置,那么write会阻塞,直到把100个字节全部交给发送缓冲区才返回。但如果socket文件描述符中有O_NONBLOCK标志,则write不阻塞,直接返回20。

为避免这些情况干扰主程序逻辑,确保读写所请求的字节数,应包装read和write函数。

当设置socket为非阻塞模式时,要用select()或epoll()判断什么时候可正常写入或读出。

  • write

sszie_t write(int fd, const void *buf, size_t count);

return:成功,返回写入的字节数;失败-1。

在网络程序中,当我们向socket写时有两种可能:

  1. write的返回值大于0,表示写了部分或者全部的数据。
  2. 返回值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误,应重试。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接,返回-1)。
  3. 此外还有可能socket为非阻塞(O_NONBLOCK),当缓冲区满时,立即返回0。(我的想法) ----错误想法,fd设置为非阻塞时,不能写立即返回-1,设置errno为EAGAIN或EWOULDBLOCK(man write ERRORS)。
  4. 返回0时,表示未写数据,继续写即可。

int my_write(int fd, void *buffer, int len){

  int bytes_left;

  int written_bytes;

  char *ptr;

  ptr = buffer;

  bytes_left = len;

  while(bytes_left > 0){

    written_bytes = write(fd, ptr, bytes_left);

    if(writte_bytes <= 0){   //出错了

      if(errno == EINTR && written_bytes < 0)    // 中断错误,继续写。

        writen_bytes = 0;

      else         //其他错误,直接退出

        return -1;

    }

bytes_left -= writen_bytes;

ptr += written_bytes;
}

return len;

}

  • read

ssize_t read(int fd, void *buf, size_t count);

return:成功,返回读取到的字节数;失败-1。

返回值为0,表示已经读到文件的结束;返回值小于0 表示出现了错误。如果错误为EINTR说明读是由中断引起的(继续读),如果是ECONNREST表示网络连接出了问题。

read()阻塞时,一直等,等于0表示文件结束或网络连接关闭;read()非阻塞,无数据可读时立即返回-1,errno为EAGAIN(若一直读,一直返回-1,errno为EAGAIN)。

int my_read(int fd,void *buffer,int length){

  int bytes_left;

  int bytes_read;

  char *ptr;

  bytes_left=length;

  while(bytes_left>0){

    bytes_read=read(fd,ptr,bytes_left);

    if(bytes_read<0){

      if(errno==EINTR)          // 中断引起的,继续读

        bytes_read=0;

      else

        return(-1);          //其他原因,直接退出

    }

    else if(bytes_read==0)     // 对方close连接(收到FIN包)

      break;

    bytes_left-=bytes_read;

    ptr+=bytes_read;

  }

return(length-bytes_left);

}

  • recvfrom

int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr * from, int *fromlen);

  • sendto

int sendto(int sockfd, const void *msg, int len, unsigned int flags, struct sockaddr *to, int tolen);

注:如果对信息的来源不感兴趣,可以将from和fromlen设置为NULL。

socket数据收发的更多相关文章

  1. Silverlight Socket 实现收发信息

    原文 http://www.cnblogs.com/ZetaChow/archive/2009/05/16/2237347.html 刚接触Silverlight的时候,除了其异步应用WCF.流媒体. ...

  2. java网络编程——多线程数据收发并行

    基本介绍与思路 收发并行 前一篇博客中,完成了客户端与服务端的简单TCP交互,但这种交互是触发式的:客户端发送一条消息,服务端收到后再回送一条.没有做到收发并行.收发并行的字面意思很容易理解,即数据的 ...

  3. C# 实现的多线程异步Socket数据包接收器框架

    转载自Csdn : http://blog.csdn.net/jubao_liang/article/details/4005438 几天前在博问中看到一个C# Socket问题,就想到笔者2004年 ...

  4. AS3: Socket 数据包 收 发

    AS3.0中使用Socket使用tcp服务器协议,它是一种流协议,不停的将分片传输给客户端,P作为流,发包是不会整包到达的,而是源源不断的. 它不同于UDP服务器协议,UDP作为数据包协议,整包到达. ...

  5. 项目总结22:Java UDP Socket数据的发送和接收

    项目总结22:Java UDP Socket数据的发送和接收 1-先上demo 客户端(发送数据) package com.hs.pretest.udp; import java.io.IOExcep ...

  6. FPGA的GTP(aurora 协议)高速串行接口数据收发(转)

    reference:https://blog.csdn.net/qq_40261818/article/details/83039829 PG046-Aurora 8B/10B  Logicore I ...

  7. STM32 使用Cubemx 建一个USB(HID)设备下位机,实现数据收发

    这里我主要说一下如何做一个USB下位机,这里主要分3部分:1.建立工程:2.添加报文描述符:3.数据的传输.这里就不讲USB的理论知识了,有想要了解的自行百度一下就可以了. 建立工程:工程建立参考:h ...

  8. HAL UART DMA 数据收发

    UART使用DMA进行数据收发,实现功能,串口2发送指令到上位机,上位机返回数据给串口2,串口2收到数据后由串口1进行转发,该功能为实验功能 1.UART与DMA通道进行绑定 void HAL_UAR ...

  9. 转载 STM32 使用Cubemx 建一个USB(HID)设备下位机,实现数据收发

    STM32 使用Cubemx 建一个USB(HID)设备下位机,实现数据收发  本文转载自 https://www.cnblogs.com/xingboy/p/9913963.html 这里我主要说一 ...

随机推荐

  1. 使用git 将自己的本地文件git到github上面的完整过程

    1.  首先在github网站上新建一个仓库,复制仓库地址(HTTP形式或者SSH形式,后者利用SSH,在最后一步push 的时候可以不用输入用户名和密码). 2.  在本地某个你想要的(文件夹)目录 ...

  2. Squid调试和故障处理

    http://blog.zhdata.com/tag/squid第16章 调试和故障处理 16.1 一些通用问题 在讨论通用debug前,我先提起一些经常发生的问题. 16.1.1 “Failed t ...

  3. android 手机红外遥控器实现

    经过连续几天的编制,安卓手机代码终于完成了,目前已经将我宿舍,家里,集控室的红外遥控电气设备完好的遥控了,另外还遥控了我的D7000相机,不错终于完工了.代码分为二类:各种电视.相机.等等遥控编码最简 ...

  4. C# 小叙 Encoding (一)

    前言 众所周知计算机只能识别二进制数字,如1010,1001.我们屏幕所看到的文字,字符都是和二进制转换后的结果.将我们的文字按照某种规则转换二进制存储在计算机上,这一个过程叫字符编码,反之就是解码. ...

  5. Google Map 学习过程中的代码

    <!DOCTYPE html><html> <head> <title>Simple click event</title> <met ...

  6. JSP开发中对jstl的引用方式(标签库引用)

    创建标签库引用文件taglibs.inc 一 采用本地标签库的taglibs.inc文件 <%--struts库标签 --%> <%@ taglib uri="/WEB-I ...

  7. Devexpress ASPxPivotGrid 按某列排序,以及把GrandTotal修改掉

    <div> <table width="100%" border="0" cellspacing="0" cellpadd ...

  8. Python2 元组 cmp() 方法

    描述 Python2 元组 cmp() 方法用于比较两个元组,如果 T1< T2返回 -1, 如果 T1== T2返回 0, 如果 T1> T2返回 1. 语法 cmp() 方法语法: c ...

  9. mysql 表锁——读锁和写锁

    注意, 0.表的索引类型必须是InnoDB.相关链接:http://www.cnblogs.com/CyLee/p/5579672.html 1.如果你使用Navicat Premium,有可能会出现 ...

  10. 零基础学python》(第二版)

    ---恢复内容开始--- 零基础学python>(第二版) python学习手册 可以离线下载,  .chn格式, 插入小幽默笑话,在学习累的时候看看笑话 放松一下 欢迎下载转载,请注明出处,谢 ...