一、概述

1、socket是一种进程间通信方式,既可以用于一台机器,也可以用于网络。常用语C/S模型。

2、可以跨越Windows和Linux操作系统,可以跨越不同语言。

3、注意网络字节序和主机字节序的转换;可以不用判断,直接调用函数,函数内部会做出判断。

二、socket()

1、<sys/types.h><sys/socket.h>

2、int socket(int domain,int type,int protocol);

3、domain:创建套接字所使用的协议簇(地址)

  • AF_UNIX:本机

  • AF_INET:IPv4

  • AF_INET6:IPv6

  • AF:address family

4、type:套接字类型

  • SOCK_STREAM:流,用于tcp

  • SOCK_DGRAM:数据报,用于UDP

  • SOCK_RAW:原始,可以操作ICMP等

5、protocol:协议,Linux下默认为0,即由domain和type可以确定所使用的协议。

6、返回值:成功后,返回套接字;否则,返回-1,错误存入errno。

7、可以理解为:domain是网络层的参数,type是传输层的参数。

三、bind()

1、<sys/types.h><sys/socket.h>

2、int bind(int sockfd,sockaddr* my_addr,socklen_t addlen);

3、作用:将IP地址+端口和socket绑定。一般服务器需要,客户端不需要bind()。但是实际上,对于UDP,客户端在发送时,内核都会自动绑定(将IP地址+端口和socket绑定);对于TCP,个人认为应该不会,因为服务器端通过连接返回,所以客户端不用bind()。

4、sockfd:socket文件描述符;addlen:sockaddr结构的长度。

5、返回值:成功0,失败,返回-1,错误存入errno。

6、struct sockaddr是通用的套接字地址,实际上很少使用,而是使用sockaddr_in。

7、struct sockaddr_in(TCP/IP协议簇常用)

(1)头文件:<netinet/in.h>

(2)定义

struct sockaddr_in{

unsigned short sin_family;//AF_INET(TCP/IP)

unsigned short sin_port;//0-1023特用

struct in_addr sin_addr;//32位IP地址

unsigned char sin_zero[8];//填充

};

struct in_addr{

unsigned long s_addr;//或in_addr_t

};

s_addr可以设置为INADDR_ANY,表示本机上的所有IP(多宿主主机有多个网卡)

四、listen()

1、<sys/types.h><sys/socket.h>

2、int listen(int sockfd,int backlog);

3、功能:一般在服务器端使用。初始化服务器可连接队列,由于是顺序处理连接请求,所有将暂时不能处理的放到等待队列里面,长度由backlog确定。

4、backlog:连接队列的最大长度,一般为20,有时为10或5。

5、返回值:成功0,失败,返回-1,错误存入errno。

6、注意,listen()是非阻塞调用,listen()执行后,套接字处于监听状态,进程处于执行状态,即一个套接字listen()一次即可,直至进程退出才会失效。

五、accept()

1、<sys/types.h><sys/socket.h>

2、int accept(int sockfd,sockaddr *addr,socklen_t *addrlen);

3、功能:当一个客户端的连接请求到达服务器监听接口时,在队列中等待;accept()执行后,返回一个套接字描述表示一个客户端的连接,并用这个套接字进行send()和recv()。

4、返回值:成功后,返回代表连接的套接字(性质与sockfd相同),失败,返回-1,错误存入errno。

5、若sockfd是阻塞的,且连接队列为空,则accept()将被阻塞知道有连接请求为止;若为非阻塞的,且连接队列为空,则accept()返回-1,errno被设置为EAGAIN。

6、注意,accept发生的阶段是三次握手之后,即从连接队列中取出相应连接进行处理。

六、connect()

1、<sys/types.h><sys/socket.h>

2、int connect(int sockfd,sockaddr *addr,socklen_t addrlen);

3、功能:一般在客户端使用。客户端发出连接请求,因为客户端的地址不重要(服务器通过连接返回),因此客户端无需bind()。一个socket只能connect一个主机。

4、返回值:成功0,失败,返回-1,错误存入errno。

七、send()和recv()

1、<sys/types.h><sys/socket.h>

2、函数原型

  • ssize_t send(int conn_fd,const void *msg,size_t len,int flags);

  • ssize_t recv(int conn_fd,void *buf,size_t len,int flags);

3、服务器端和客户端都可以send()和recv()。注意,send()只是将数据由msg存入socket的缓冲区里面,具体的发送操作由操作系统完成;同理,recv()是将socket缓冲区里面的数据读到buf中,具体的接收操作也是由操作系统完成的。

4、参数说明

  • conn_fd:连接好的套接字

  • msg/buf:发送或接受数据的缓冲区

  • len:缓冲区长度

  • flags:控制选项,一般为0。

5、返回值:成功,返回实际发送或接受的字节数,失败,返回-1,错误存入errno。

6、疑问:对于UDP,也是在缓冲区中取出,但是UDP是有边界的呀??todo

7、可以利用recv的返回值以及等待时间,来判断是否停止接受。

八、close()

1、<unistd.h>

2、int close(int fd);

3、关闭一个套接字描述符。

4、返回值:成功0,失败,返回-1,错误存入errno。

九、地址转换

1、<arpa/inet.h>

2、点分十进制字符串转化为unsigned long/in_addr_t

in_addr_t inet_addr(const char* cp);

3、in_addr转化为点分十进制字符串:inet_ntoa();

十、TCP与UDP的差异

1、UDP在connect的时候,不会进行三次握手,甚至不会发送任何数据包;只是发送/接收的时候不再需要指定对方的地址(内核记录了IP地址和端口)。

因此我认为,UDP客户端可以不connect。

2、UDP服务器端不需要listen和accept,可以直接接收;但是有了之后,服务端也记录了客户端的IP地址和端口,每次发送和接收的时候不需要sendto()、recvfrom()。

3、对于服务器端:UDP的服务器端可以不需要绑定,使用sendto和recvfrom,但是TCP的服务器端必须绑定,因为在sendto和recvfrom之前还要listen和accept。

对于客户端:TCP和UDP都不需要bind。TCP因为建立了连接,可以按照连接返回(其实连接还是按IP+端口确定的)。UDP客户端在第一次发送时,内核也会将IP地址和端口与socket绑定。

注意,绑定的含义是将socket与IP地址和端口绑定;无论是否绑定,数据包中肯定是有IP地址和端口的。

4、综合1、2、3可知,UDP的客户端可以新建一个socket后,直接使用sendto发送数据;UDP的服务器端可以新建一个socket后,直接用recvfrom接收数据。

5、区分TCP和UDP的方式:socket的类型是SOCK_STREAM还是SOCK_DGRAM;而不是使用了哪些函数,因为由上述可知,TCP与UDP使用的函数可能相同。

十一、阻塞与非阻塞

1、受影响的函数:connect、accept、send、recv等。

(1)connect(TCP)

  • 非阻塞:connect会立即返回EINPROGRESS错误,表示连接操作正在进行中,但是仍未完成;同时TCP的三路握手操作继续进行;在这之后,我们可以调用select来检查这个链接是否建立成功。

  • 阻塞:线程阻塞,若连接在超时之前建立,则返回0;若超时(一般为75s-几分钟),则返回负数。

(2)accept(TCP):见五、5

(3)send、recv

  • 非阻塞:如果缓冲区有空间或者有内容,立马返回实际放入或取出的字节数,如果没有,立马返回-1。

  • 阻塞:如果有足够空间或者内容,肯定就返回n了;如果完全没有空间或者内容,肯定就返回-1了;但是如果有部分空间或者内容,是等待呢,还是返回??todo

2、阻塞模式效率低,编程简单,适用于小型系统;非阻塞模式效率高,但是编程复杂,适用于大型系统。

3、(貌似)SOCK_STREAM默认是阻塞的,SOCK_DGRAM默认是非阻塞的。

4、fctnl或者select可以转换socket的阻塞属性。

socket套接字编程的更多相关文章

  1. linux网络环境下socket套接字编程(UDP文件传输)

    今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...

  2. linux网络编程-(socket套接字编程UDP传输)

    今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...

  3. socket套接字编程 HTTP协议

    socket套接字编程  套接字介绍  1. 套接字 : 实现网络编程进行数据传输的一种技术手段  2. Python实现套接字编程:import  socket  3. 套接字分类 >流式套接 ...

  4. socket 套接字编程

    今日内容 socket 套接字编程 简易服务端与客户端代码实现 通信循环 黏包现象(TCP协议) 报头制作.struct 模块.封装形式 内容详细 一.socket 套接字编程 实现一款能够进行数据交 ...

  5. Linux之socket套接字编程20160704

    介绍套接字之前,我们先看一下传输层的协议TCP与UDP: TCP协议与UDP协议的区别 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UD ...

  6. 基于TCP协议的socket套接字编程

    目录 一.什么是Scoket 二.套接字发展史及分类 2.1 基于文件类型的套接字家族 2.2 基于网络类型的套接字家族 三.套接字工作流程 3.1 服务端套接字函数 3.2 客户端套接字函数 3.3 ...

  7. 基于TCP连接的socket套接字编程

    基于TCP协议的套接字编程(简单) 服务端 import socket server = socket.socket() server.bind( ('127.0.0.1', 9999) ) serv ...

  8. day31 socket套接字编程

    为什么要有套接字编程? 在上节课的学习中,我们学习了OSI七层协议,但是如果每次进行编程时我们都需要一层一层的将各种协议使用在我们的程序中,这样编写程序实在是太麻烦了,所以为了让程序的编写更加的简单, ...

  9. socket套接字编程(1)——基本函数

    TCP交互流程: 服务器:1. 创建socket:2. 绑定socket和端口号:3. 监听端口号:4. 接收来自客户端的连接请求:5. 从socket中读取字符:6. 关闭socket. 客户端:1 ...

  10. 19、网络编程 (Socket套接字编程)

    网络模型 *A:网络模型 TCP/IP协议中的四层分别是应用层.传输层.网络层和链路层,每层分别负责不同的通信功能,接下来针对这四层进行详细地讲解. 链路层:链路层是用于定义物理传输通道,通常是对某些 ...

随机推荐

  1. Java中四种遍历List的方法

    package com.ietree.basic.collection.loop; import java.util.ArrayList; import java.util.Iterator; imp ...

  2. 在Angular项目下使用Umeditor

    Umeditor是百度旗下的开源富文本编辑器项目,目前用于百度贴吧,是ueditor的迷你版本. 公司的Angular后台管理项目需要上传一些新闻,用Umeditor十分适合.但是目前官方只提供Jsp ...

  3. Android触摸事件的应用

    前言 上一篇讲了Android触摸事件的传递机制,具体可以看这里 初识Android触摸事件传递机制.既然知道Android中触摸事件的传递分发,那么它能解决什么样的问题,在我们实际开发中如何应用,这 ...

  4. poj3320尺取法

    Jessica's a very lovely girl wooed by lots of boys. Recently she has a problem. The final exam is co ...

  5. poj3020二分图匹配

    The Global Aerial Research Centre has been allotted the task of building the fifth generation of mob ...

  6. iOS 制作自动打包脚本 Xcode8.3.2

    本文包含以下内容: 前言 1.shell脚本的编写 2.xcodebuild命令 3.完整的可用示例 参考资料 前言 做iOS开发,打包APP是比较频繁的事情,每次都手动去配置一堆东西确实是比较乏味. ...

  7. Collection<E>、Iterable<T>和Iterator<E>接口

    Collection接口 public interface Collection<E>extends Iterable<E> Collection接口主要包含以下方法: Ite ...

  8. 最常用的缓存技术---redis入门

      Redis简介 Redis是基于内存,也可以基于磁盘持久化nosql数据库,使用c语言开发. 数据存储结构:key-value 安装环境准备 Redis使用c语言开发,需要使用gcc编译程序进行编 ...

  9. hive的表的基本操作

    环境简介 实验环境使用的是cloudera-quickstart-vm-5.0环境. 内容摘要 创建表 修改表名 修改表中的列名 添加列 删除列 替换列 正文 Alter Table 语句 上面所述的 ...

  10. 一次基于Vue.Js用户体验的优化

    .mytitle { background: #2B6695; color: white; font-family: "微软雅黑", "宋体", "黑 ...