网络编程套接字(一)
网络编程套接字(一)
文章目录
- 网络编程套接字(一)
- 一、基础知识
- 二、sock编程接口
一、基础知识
1. 理解源IP地址和目的IP地址
在IP数据包头部中,有两个IP地址,分别叫源IP地址和目的IP地址。这两个很好理解,见名知义。
思考: 我们光有IP地址就可以完成通信了嘛? 想象一下发qq消息的例子, 有了IP地址能够把消息发送到对方的机器上,但是还需要有一个其他的标识来区分出, 这个数据要给哪个程序进行解析。
2. 认识端口号
端口号是传输层协议内容 :
a. 端口号是一个2字节的16为整数
b.端口号是用来标识一个进程,告诉操作系统,当前这个数据要交给那个进程去处理
c.IP地址 + 端口号 能够唯一标识网络上的某一台主机的某一个进程
d.一个端口号只能被一个进程占用3. 理解端口号和进程ID
一个进程可以绑定多个端口号,但是一个端口号只能被一个进程绑定
一个网络应用程序对应一个端口
一个端口对应一至多个进程;
一个进程对应一至多个线程
4. 理解源端口号和目的端口号
在传输层协议(TCP/UDP)的数据段中有两个端口号,分别叫源端口号和目的端口号
源端口就是指本地端口,源端口就是本机程序用来发送数据的端口。
目的端口就是远程端口,目的端口就是对方主机用哪个端口接收
5. 初识TCP协议
传输层协议
有链接(相当于打电话)
可靠传输(这里的可靠只是相对而言,“可靠“具体是指发送/接收数据的成功与否自己知道,并不是100%传输成功)
面向字节流
6. 初识UDP协议
传输层协议
无连接(如消息,短信)
不可靠传输(“不可靠“具体是指发送/接收数据的成功与否自己不知道,并不是说传输数据一定是不可靠的)
面向数据报
7. 网络字节序(
大端序
)我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,
磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢?发送主机通常将发送缓存区中的数据按照内存地址从低到高的顺序发出
接收主机通常把从网络上接收到的字节依次保存在接受缓存区中,也就是按内存地址从低到高的顺序保存的
因此,网络数据流的地址应该这样规定:先发出的数据是低地址,后发出的数据是高地址
TCP/IP协议规定,网络数据采用
大端字节序
,即先低地址后高地址不论主机是大端机还是小端机,都会按造这个TCP/IP规定的网络字节序来发送/接受数据
如果当前发送主机是小端机,就需要先将数据转为大端;否则直接忽略这一步
8.网络字节序和主机字节序的转换
目的:为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
- h代编host(主机),n代表网络(network),l代表32位长整数,s表示16位短整数
- 例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送
- 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回;
- 如果主机是大端字节序,这些 函数不做转换,将参数原封不动地返回
二、sock编程接口
- 1.socket函数—>创建socket
int socket(int domain, int type, int protocol);
- 作用:创建一个socket文件描述符(相当于整个socket编程的操作句柄),也就是文件描述符表的下表,根据前面所说,可以用一个端口号关联一个进程,在这里就是拿端口号和一个socket绑定在一起
- 参数:
参数 | 作用 |
---|---|
domain | domain 为地址族(Address Family),也就是 IP 地址类型,常用的有 AF_INET 和 AF_INET6。AF_INET 表示 IPv4 地址,例如 127.0.0.1;AF_INET6 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B。 |
type | type 为数据传输方式/套接字类型,常用的有 SOCK_STREAM(流格式套接字/面向连接的套接字) 和 SOCK_DGRAM(数据报套接字/无连接的套接字) |
protocol | protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,分别表示 TCP 传输协议和 UDP 传输协议。如果操作系统可以根据前面两个参数成功推演出协议类型,那么此处可以直接为0 |
有了地址类型和数据传输方式,还不足以决定采用哪种协议吗?为什么还需要第三个参数呢?
正如大家所想,一般情况下有了 domain 和 type 两个参数就可以创建套接字了,操作系统会自动推演出协议类型
除非遇到这样的情况:有两种不同的协议支持同一种地址类型和数据传输类型。如果我们不指明使用哪种协议,操作系统是没办法自动推演的。
例如
如果使用 SOCK_STREAM 传输数据,那么满足这两个条件的协议只有 TCP,因此可以这样来调用 socket() 函数:
int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //IPPROTO_TCP表示TCP协议
- 这种套接字称为 TCP 套接字。
- 如果使用 SOCK_DGRAM 传输方式,那么满足这两个条件的协议只有 UDP,因此可以这样来调用 socket() 函数:
int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //IPPROTO_UDP表示UDP协议
- 这种套接字称为 UDP 套接字。
- 上面两种情况都只有一种协议满足条件,可以将 protocol 的值设为 0,系统会自动推演出应该使用什么协议,如下所示:
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字
- 2.bind函数—>绑定端口信息
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
- 功能:bind为套接字sockfd指定本地地址my_addr
- 参数
参数 | 功能 |
---|---|
sockfd | socket创建出的套接字,也就是文件描述符 |
my_addr | 该参数是一个指向结构sockaddr的指针,sockaddr封装了地址的类型、IP地址、端口号,用的时候需要把这些成员变量附上值,也就是绑定的过程,绑定本地主机的IP端口号信息 |
addrlen | 这个参数是第二个参数的大小,直接sizeof即可 |
- 3.listen函数—>开始监听
int listen(int s, int backlog)
- 功能:调用listen使其能够自动接收到来的连接并且为连接队列指定一个长度限制.
- listen调用仅适用于 SOCK_STREAM 或者SOCK_SEQPACKET 类型的套接字(因为前面已经创建号套接字和绑定好端口号相关信息,但是别人是无法访问到我的
- 通过listen就可以和我链接到,但是处于链接队列的所有请求都是处于倾听状态)
- 参数:
参数 | 功能 |
---|---|
s | socket套接字 |
backlog | 指定完成连接队列的最大长度.如果一个连接请求到达时未完成连接队列已满,那么客户端将接收到错误 |
- 4.accept函数—>接受请求
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
- 功能:它从未完成连接队列中取出第一个连接请求,
创建一个和参数s属性相同的连接套接字,
并为这个套接字分配一个文件描述符,然后以这个描述符返回.新创建的描述符不再处于倾听状态,原套接字s不受此调用的影响. - 注意任意一个文件描述符标志(任何可以被fcntl以参数F_SETFL设置的值,比如非阻塞式或者异步状态)不会被 accept.
- 参数
参数 | 功能 |
---|---|
s | 套接字 |
addr | 是一个指向结构sockaddr的指针,是输出型参数,这个结构体以连接实体地址填充. |
addrlen | 是一个实时参数: 它的大小应该能够足以容纳参数 addr所指向的结构体;在函数返回时此参数将以字节数表示出返回地址的 实际长度.若 addr 使用NULL作为参数,addrlen将也被置为NULL |
- 5.connect函数—>建立链接
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
- 功能:connect()系统调用将文件描述符sockfd引用的套接字连接到addr指定的地址
- 参数
参数 | 功能 |
---|---|
sockfd | 套接字 |
addr | 该参数是一个指向结构sockaddr的指针,sockaddr封装了地址的类型、IP地址、端口号,用的时候需要把这些成员变量附上值 |
addrlen | sizeof(addr) |
- 6.recv函数
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
- 功能:接收远端主机传来的数据,并把数据存到由参数buf 指向的内存空间
- 参数
参数 | 功能 |
---|---|
sockfd | sockfd为前面accept的返回值.即new_fd,也就是新的套接字 |
buf | 存储接收到的数据的缓冲区 |
一般为0 |
- 7.recvfrom函数
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
- 参数
参数 | 作用 |
---|---|
src_addr | 输出型参数,数据发送者地址,函数调用后该地址结构被填充 |
addrlen | sizeof(src_addr) |
- 8.send函数
int send(int s, const void *msg, size_t len, int flags);
- 功能:发送数据给指定的远端主机
- 参数
参数 | 功能 |
---|---|
s | s为前面accept的返回值.即new_fd |
msg | msg一般为常量字符串,也就是服务器返回给客户端的内容 |
len | 发送数据的长度 |
flags | 通常为0 |
- 9.sendto函数
int sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
- 参数
参数 | 作用 |
---|---|
to | 指向接收数据的主机地址信息的结构体(sockaddr_in需类型转换) |
tolen | sizeof(to) |
网络编程套接字(一)相关推荐
- 网络编程套接字(四)
网络编程套接字(四) 文章目录 网络编程套接字(四) 一.实现tcp服务器多用户版本(多进程.多线程.线程池版本) 一.实现tcp服务器多用户版本(多进程.多线程.线程池版本) tcp_process ...
- 网络编程套接字(三)
网络编程套接字(三) 文章目录 网络编程套接字(三) 一.实现简单的Tcp服务器(单用户) 一.实现简单的Tcp服务器(单用户) tcp_socket.hpp #pragma once #includ ...
- 网络编程套接字(二)
网络编程套接字(二) 文章目录 网络编程套接字(二) 一.简单的UDP网络程序 一.简单的UDP网络程序 封装udp_socket #pragma once #include <cstdio&g ...
- 详细讲解 —— 网络编程套接字(Java EE初阶)
网络编程套接字 1 认识网络编程套接字 2 UDP 数据报套接字编程 2.1 UPD服务端 2.1 UDP客户端 2.3 结果测试 3 TCP流套接字编程 3.1 TCP服务端 3.2 TCP客户端 ...
- 【javaEE】网络编程套接字
To u&me: 努力经营当下,直至未来明朗 文章目录 前言 一.网络编程(没时间可以跳过) 一)网络编程了解 二)相关基本概念 二.Socket套接字 三.数据报套接字通信(UDP) 写一个 ...
- Java网络编程套接字
文章目录 1.网络编程基础 2.什么是网络编程 3.网络编程中的基本概念 3.1.发送端和接收端 3.2 请求和响应 3.3 客户端和服务端 3.4 常见的客户端服务端模型 4.Socket套接字 4 ...
- UNIX网络编程---套接字编程简介(三)
UNIX网络编程---套接字编程简介 一.概述 从这里开始正式开始网络编程之旅,所有的函数都是基本的库函数.这些都是网络编程的基础.Come on!!!! 二.套接字地址结构 大多数套接字函数都需要一 ...
- 【网络编程套接字(一)】
网络编程套接字(一) 理解源IP地址和目的IP地址 理解源MAC地址和目的MAC地址 理解源端口号和目的端口号 PORT VS PID 认识TCP协议和UDP协议 网络字节序 socket编程接口 s ...
- Linux·网络编程套接字(三)
目录 简单的TCP英译汉服务器 简单回顾 更改handler方法 地址转换函数 字符串IP转整数IP 整数IP转字符串IP 绑定失败问题 TCP协议通讯流程 通讯流程总览 三次握手的过程 数据传输的过 ...
最新文章
- poj1564 Sum It Up dfs水题
- 智源“高能对撞粒子分类挑战赛”开启,品鉴宇宙粒子的独特“味道”
- 如何处理 android 方法总数超过 65536 . the number of method references in a .dex file exceed 64k
- Java程序员周末时间搞锭银行信息管理系统毕业设计(java+springboot+mybatis+mysql+vue+elementui)等实现
- mysql 连接失败的日志(或者输出)结果分析
- 韩国巨型机器人曝光,走一步地动山摇
- quot;数据结构翻转课堂quot;答疑实录——链表
- python 新浪博客_Python实现新浪博客备份的方法
- python 视频转场_Python 带你高效创作短视频,视频创作秀到飞起!!!
- 我是如何入门机器学习的呢
- 1000以内完数c语言程序_求1000以内完数 c语言 。。
- 微信服务号新手入门讲解、第二章(创建菜单)
- 《三体2:黑暗森林》读后感
- revel MySQL_使用Revel(go)开发网站
- jquery ui 主题_使用jQuery UI主题
- DDR5内存条容量计算
- stm32 外部中断不起作用
- 算法问题:整数除法详解(Java方向)
- Docker 无法启动 Failed to start LSB: Create lightweight, portable, self-sufficient containers.
- Java学习基础(二)