当前位置: 首页 > news >正文

Linux 网络编程 + 笔记

协议:一组规则

分层模型结构:

  • OSI七层模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
  • TCP/IP 4层模型:链路层/网络接口层、网络层、传输层、应用层
    • 应用层:http、ftp、nfs、ssh、telnet、
    • 传输层:TCP、UDP
    • 网络层:IP、ICMP、IGMP
    • 链路层:以太网帧协议、ARP

C/S模型和B/S模型

  • C/S模型:client-server
  • B/S模型:browser-server

网络传输流程:

  • 数据没有封装之前,是不能在网络中传递
  • 数据-》应用层-》传输层-》网络层-》链路层  --- 网络环境

以太网帧协议:

  • ARP协议:根据IP地址获取mac地址
  • 以太网帧协议:根据mac地址,完成数据包传输

IP协议:

  • 版本: IPv4、IPv6  -- 4位
  • TTL:time to live (设置数据包在路由节点中的跳转上限,每经过一个路由节点,该值-1, 减为0的路由,有义务将该数据包丢弃)
  • 源IP:32位 -- 4字节 
192.168.1.108 --- 点分十进制 IP地址(string)
  • 目的IP:32位--- 4字节

IP地址:可以在网络环境中,唯一标识一台主机

端口号:可以进行网络通信的一台主机上,唯一标识一个进程

IP地址+端口号:可以在网络环境中,唯一标识一个进程

UDP协议16位:源端口号     2^16 = 6553616位:目的端口号TCP协议16位:源端口号     2^16 = 6553616位:目的端口号32序号32确认序号6个标志位16位窗口大小       2^16 = 65536

网络套接字:socket

  • 一个文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现)
  • 在通信过程中,套接字一定是成对出现的

网络字节序:

  • 小端法:(pc本地存储)    高位存高地址,低位存低地址            int a = 0x12345678
  • 大端法:(网络存储)        高位存低地址,低位存高地址         
    htonl --> 本地--》网络 (IP)			192.168.1.11 --> string --> atoi --> int --> htonl --> 网络字节序htons --> 本地--》网络 (port)ntohl --> 网络--》 本地(IP)ntohs --> 网络--》 本地(Port)

 注意:htonl --> 本地 --> 网络(IP)

192.168.1.11 --> string --> atoi --> int --> htonl --> 网络字节序

IP地址转换函数

  1. inet_pton
  2. inet_ntop
  • 本地字节序(string IP) ---> 网络字节序 
// 本地字节序(string IP) ---> 网络字节序
int inet_pton(int af, const char *src, void *dst);af: AF_INET,AF_INET6src:传入,IP地址(点分十进制)dst:传出转换后的 网络字节序的 IP地址返回值:成功:   1异常:   0,说明src指向的不是一个有效的ip地址失败:  -1
NAMEinet_pton - convert IPv4 and IPv6 addresses from text to binary formSYNOPSIS#include <arpa/inet.h>int inet_pton(int af, const char *src, void *dst);DESCRIPTIONThis  function converts the character string src into a network addressstructure in the af address family, then  copies  the  network  addressstructure  to dst.  The af argument must be either AF_INET or AF_INET6.dst is written in network byte order.
  • 网络字节序  ---> 本地字节序(string IP) 
// 网络字节序  ---> 本地字节序(string IP)
const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);af: AF_INET,AF_INET6src: 网络字节序IP地址dst: 本地字节序(string IP)size: dst的大小返回值: 成功: dst失败: NULL
NAMEinet_ntop - convert IPv4 and IPv6 addresses from binary to text formSYNOPSIS#include <arpa/inet.h>const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);DESCRIPTIONThis  function  converts  the  network  address  structure src in the afaddress family into a character string.  The resulting string is  copiedto  the buffer pointed to by dst, which must be a non-null pointer.  Thecaller specifies the number of bytes available in  this  buffer  in  theargument size.
  • sockaddr地址结构: IP + Port  --> 在网络环境中唯一标识一个进程 
sockaddr地址结构: IP + Port  --> 在网络环境中唯一标识一个进程struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(8080);
#if 0int dst;inet_pton(AF_INET,"192.168.1.100",(void*)dst);   addr.sin_addr.s_addr = dst;
#else// 取出系统中有效的任意IP地址(二进制类型)addr.sin_addr.s_addr =  htonl(INADDR_ANY);bind(fd,(struct sockaddr*)&addr,sizeof(addr));

  • socket函数,创建一个套接字
socket函数#include <sys/socket.h>// 创建一个套接字int socket(int domain, int type, int protocol);domain: AF_INET,AF_INET6type: SOCK_STREAM,SOCK_DGRAMprotocol: 0返回值:成功: 新套接字所对应文件描述符失败: -1 errno
NAMEsocket - create an endpoint for communicationSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int socket(int domain, int type, int protocol);DESCRIPTIONsocket()  creates  an  endpoint  for  communication  and  returns a filedescriptor that refers to that endpoint.  The file  descriptor  returnedby  a  successful  call  will be the lowest-numbered file descriptor notcurrently open for the process.
  • bind函数 
#include <arpa/inet.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);sockfd: socket 函数返回值struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(8080);addr.sin_addr.s_addr = htonl(INADDR_ANY);addr:传入参数(struct sockaddr*)&addraddrlen:sizeof(addr) 地址结构的大小返回值:成功: 0失败: -1 errno
NAMEbind - bind a name to a socketSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);DESCRIPTIONWhen  a  socket  is  created  with  socket(2), it exists in a name space(address family) but has no address assigned to it.  bind() assigns  theaddress specified by addr to the socket referred to by the file descrip‐tor sockfd.  addrlen specifies the size, in bytes, of the address struc‐ture  pointed  to  by  addr.   Traditionally,  this  operation is called“assigning a name to a socket”.It is normally necessary to assign a local address using bind() before aSOCK_STREAM socket may receive connections (see accept(2)).
  • listen函数,设置同时与服务器建立连接的上限数(同时进行3次握手的客户端数量)
// 设置同时与服务器建立连接的上限数(同时进行3次握手的客户端数量)
int listen(int sockfd, int backlog);sockfd: socket 函数返回值backlog: 上限数值,最大值为128返回值:成功: 0失败: -1 errno
NAMElisten - listen for connections on a socketSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int listen(int sockfd, int backlog);DESCRIPTIONlisten()  marks  the  socket  referred to by sockfd as a passive socket,that is, as a socket that will be used  to  accept  incoming  connectionrequests using accept(2).The sockfd argument is a file descriptor that refers to a socket of typeSOCK_STREAM or SOCK_SEQPACKET.The backlog argument defines the maximum length to which  the  queue  ofpending  connections  for  sockfd  may  grow.   If  a connection requestarrives when the queue is full, the client may receive an error with  anindication  of  ECONNREFUSED  or,  if  the  underlying protocol supportsretransmission, the request may be ignored so that a later reattempt  atconnection succeeds.
  • accept函数,阻塞等待客户端建立连接,成功的话,返回一个与客户端成功连接的socket文件描述符
// 阻塞等待客户端建立连接,成功的话,返回一个与客户端成功连接的socket文件描述符
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);sockfd:socket 函数返回值addr:传出参数,成功与服务器建立连接的那个客户端的地址结构(IP+port)socklen_t client_addr_len = sizeof(addr);addrlen:传入传出  &client_addr_len入:addr的大小  出:客户端addr实际大小返回值:成功:能与客户端进行数据通信的 socket 对应的文件描述失败:-1,errno
NAMEaccept, accept4 - accept a connection on a socketSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);#define _GNU_SOURCE             /* See feature_test_macros(7) */#include <sys/socket.h>int accept4(int sockfd, struct sockaddr *addr,socklen_t *addrlen, int flags);DESCRIPTIONThe  accept()  system  call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET).  It extractsthe first connection request on the queue of pending connections for the listening socket, sockfd, creates  a  newconnected  socket, and returns a new file descriptor referring to that socket.  The newly created socket is not inthe listening state.  The original socket sockfd is unaffected by this call.
  • connect函数
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);sockfd: socket 函数返回值struct sockaddr_in server_addr; // 服务器地址结构server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8080);// 跟服务器bind时设定的 port 完全一致。inet_pton(AF_INET, "服务器IP地址", &server_addr.sin_addr.s_addr);addr:传入参数,服务器的地址结构addrlen:服务器的地址结构的大小返回值:成功: 0失败: -1,errno如果不使用bind绑定客户端地址结构,采用"隐式绑定".
NAMEconnect - initiate a connection on a socketSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);DESCRIPTIONThe  connect()  system  call connects the socket referred to by the filedescriptor sockfd to the address specified by addr.  The  addrlen  argu‐ment  specifies  the size of addr.  The format of the address in addr isdetermined by the address space of the socket sockfd; see socket(2)  forfurther details.If  the socket sockfd is of type SOCK_DGRAM, then addr is the address towhich datagrams are sent by default, and the  only  address  from  whichdatagrams  are  received.   If  the  socket  is  of  type SOCK_STREAM orSOCK_SEQPACKET, this call attempts to make a connection  to  the  socketthat is bound to the address specified by addr.Generally,  connection-based protocol sockets may successfully connect()only once; connectionless protocol sockets may  use  connect()  multipletimes  to change their association.  Connectionless sockets may dissolvethe association by connecting to an address with the sa_family member ofsockaddr set to AF_UNSPEC (supported on Linux since kernel 2.2).

TCP 通信流程分析: 

TCP 通信流程分析:Server:1.socket()      创建socket2.bind()        绑定服务器地址结构3.listen()      设置同时与服务器建立连接的上限数(监听上限)4.accept()      阻塞监听客户端连接5.read(fd)      读socket获取客户端数据6.小 -- 大写     toupper()7.write(fd)     8.close()Client:1.socket()       创建socket2.connect()      与服务器建立连接3.write()        写数据到socket4.read()         读转换后的数据5.显示读取结果6.close()
  • server.c
#include <arpa/inet.h>  
#include <unistd.h>  
#include <pthread.h>#include <errno.h> 
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  #include <ctype.h>  
#include <sys/socket.h>  #define SERVER_PORT 9527void sysErr(const char *msg) {perror(msg);exit(1);
}int main(int argc, char *argv[]) {int lfd = socket(AF_INET, SOCK_STREAM, 0);if (lfd == -1) sysErr("socket error");struct sockaddr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVER_PORT);server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//给服务器socket绑定地址结构int ret = bind(lfd,(struct sockaddr*)&server_addr,sizeof(server_addr));if(ret == -1) sysErr("bind error");// 设置监听上限  ret = listen(lfd,128);if(ret == -1) sysErr("listen error");struct sockaddr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);//  获取客户端地址结构大小// 阻塞等待客户端连接请求 int cfd = accept(lfd,(struct sockaddr*)&client_addr,&client_addr_len);if(cfd == -1) sysErr("accept error");// 根据accept传出参数,获取客户端 ip 和 port  char client_IP[1024];printf("client ip:%s port:%d\n",inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)),ntohs(client_addr.sin_port));char buf[BUFSIZ];while(1) {ret = read(cfd,buf,sizeof(buf));write(STDOUT_FILENO,buf,ret);  // 写到屏幕查看// 转换为大写for(int i=0;i<ret;++i) {buf[i] = toupper(buf[i]); // 小写 -- 大写  }write(cfd,buf,ret);           // 将大写,写回给客户端}close(lfd);close(cfd);return 0;
}
  • client.c
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define SERVER_PORT 9527void sysErr(const char* msg) {perror(msg);exit(EXIT_FAILURE);// EXIT_FAILURE	1
}int main(int argc, char const *argv[]) {int cfd = socket(AF_INET, SOCK_STREAM, 0);if(cfd == -1) sysErr("socket error");struct sockaddr_in server_addr; // 服务器地址结构server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVER_PORT);inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr.s_addr);int ret = connect(cfd, (struct sockaddr*)&server_addr, sizeof(server_addr));if(ret == -1) sysErr("connect error");int counter = 10;char buf[BUFSIZ];while(counter--) {char *msg = "hello server\n";write(cfd,msg,strlen(msg));ret = read(cfd,buf,sizeof(buf));write(STDOUT_FILENO,buf,ret);sleep(1);}close(cfd);return 0;
}
heheda@linux:~/Linux/test$ gcc server.c -o server -Wall -g
heheda@linux:~/Linux/test$ ./server 
heheda@linux:~/Linux/test$ gcc client.c -o client -Wall -g
heheda@linux:~/Linux/test$ ./client

未完待续~ 

相关文章:

  • BUUCTF-Real-[ThinkPHP]5-Rce
  • TPM 2.0安全算法开发示例实战 | 开发准备
  • 07-使用Package、Crates、Modules管理项目
  • 多维时序 | Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序列预测
  • Spring 事务原理总结三
  • MySQL中如何将字符串替换
  • C# 怎么判断屏幕是第几屏幕?屏幕是垂直还是水平?屏幕的分辨率?
  • 老版本O记12C上线前的一些调整
  • npm ERR! code CERT_HAS_EXPIRED
  • oracle数据回滚导致业务性能问题排查
  • 115.工业相机海康SDK开发指南(阅读)
  • IP数据云识别真实IP与虚假流量案例
  • 第二章 RocketMQ 的安装与启动
  • openGauss学习笔记-212 openGauss 数据库运维-日志参考
  • php工厂模式
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • 时间复杂度分析经典问题——最大子序列和
  • 4个实用的微服务测试策略
  • Brief introduction of how to 'Call, Apply and Bind'
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • CentOS7简单部署NFS
  • HTTP--网络协议分层,http历史(二)
  • js继承的实现方法
  • Linux下的乱码问题
  • mongo索引构建
  • Objective-C 中关联引用的概念
  • Python_OOP
  • select2 取值 遍历 设置默认值
  • SpiderData 2019年2月23日 DApp数据排行榜
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 翻译:Hystrix - How To Use
  • 警报:线上事故之CountDownLatch的威力
  • 一道面试题引发的“血案”
  • 原生js练习题---第五课
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • Spring Batch JSON 支持
  • Spring第一个helloWorld
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ​第20课 在Android Native开发中加入新的C++类
  • # Java NIO(一)FileChannel
  • ###项目技术发展史
  • #162 (Div. 2)
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (1)常见O(n^2)排序算法解析
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (9)STL算法之逆转旋转
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (南京观海微电子)——I3C协议介绍
  • (转)人的集合论——移山之道
  • (转)用.Net的File控件上传文件的解决方案
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .Family_物联网