TCP/ IP协议栈与SOCKET

tcp/ip

image.png
image.png

传输层

传输层及其以下的机制由内核提供,应用层由用户进程提供(socket编写 应用程序),应用 程序对通讯数据的含义进行解释,而传输层及其以下处理通讯的细节,将数据从一台计算机通过一定的路径发送到另一台计算机。应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部(header) ,称为封装(Encapsulation)
image.png

socket

image.png

Linux网络编程API介绍

image.png

tcp

image.png

udp

image.png

Linux网络通信流程-TCP

image.png

客户端

image.png

  1. #include <sys/types.h> // 类型定义
  2. #include <sys/socket.h> //提供网络通信函数
  3. #include<unistd.h> //针对系统调用的封装fork,pipe read write 等
  4. #include<netinet/in.h> // 互联网地址族定 义数据结构sockaddr_ in
  5. # include<arpa/inet.h> //提供IP地址转换函数
  6. #include<stdio.h>
  7. #include<string.h>
  8. //服务器 B/S C/S tcp/ip
  9. //1、创建套接字 socket
  10. //发起连接 connect
  11. //5、收发数据 send/recv
  12. //6、关闭套接字 close
  13. int main(){
  14. //1、创建套接字 socket
  15. int hSock = 0;
  16. hSock = socket(
  17. AF_INET, //协议族
  18. SOCK_STREAM, //套接字类型
  19. IPPROTO_TCP //协议类型
  20. );
  21. //发起连接 connect
  22. printf("connect......\n");
  23. struct sockaddr_in saddr;
  24. inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr);//填写服务器ip地址192.168.78.130
  25. saddr.sin_port = htons(12345); //主机字节序转换成网络字节序,服务端口
  26. saddr.sin_family = AF_INET; //网络协议
  27. int addrlen = sizeof(saddr); //地址大小
  28. connect(hSock,(struct sockaddr*)&saddr,addrlen);
  29. //5、收发数据 recv/send
  30. char buff[1024]={};
  31. recv( //接收客户消息,阻塞
  32. hSock,
  33. buff,
  34. 1024,
  35. 0
  36. );
  37. printf("接收到服务消息:%s\n",buff);
  38. send(
  39. hSock, //客户套接字
  40. "hello server", //数据包
  41. 15, //数据长度
  42. 0 //默认0
  43. );
  44. //6、关闭套接字 close
  45. close(hSock);
  46. return 0;
  47. }

服务端

image.png

  1. #include <sys/types.h> // 类型定义
  2. #include <sys/socket.h> //提供网络通信函数
  3. #include<unistd.h> //针对系统调用的封装fork,pipe read write 等
  4. #include<netinet/in.h> // 互联网地址族定 义数据结构sockaddr_ in
  5. # include<arpa/inet.h> //提供IP地址转换函数
  6. #include<stdio.h>
  7. #include<string.h>
  8. //服务器 B/S C/S tcp/ip
  9. //1、创建套接字 socket
  10. //2、绑定 bind
  11. //3、监听 listen
  12. //4、等待连接 accept
  13. //5、收发数据 send/recv
  14. //6、关闭套接字 close
  15. int main(){
  16. //1、创建套接字 socket
  17. int hSock = 0;
  18. hSock = socket(
  19. AF_INET, //协议族
  20. SOCK_STREAM, //套接字类型
  21. IPPROTO_TCP //协议类型
  22. );
  23. //2、绑定 bind
  24. struct sockaddr_in saddr;
  25. inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr);//填写服务器ip地址192.168.78.130
  26. saddr.sin_port = htons(12345); //主机字节序转换成网络字节序,服务端口
  27. //0x12345678 => 78 56 34 12 小端
  28. //0x12345678 => 12 34 56 78 大端
  29. //现在的cpu都是小端,1234读到内存会变成34 12
  30. saddr.sin_family = AF_INET; //网络协议
  31. int addrlen = sizeof(saddr); //地址大小
  32. bind(hSock,(struct sockaddr*)&saddr,addrlen); //绑定服务器地址
  33. //3、监听 listen
  34. printf("listen......\n");
  35. listen(hSock,SOMAXCONN); //一次最多多少个客户连接上服务器
  36. //4、等待连接 accept
  37. struct sockaddr_in clientaddr={};
  38. int clientsock = accept( //返回客户端套接字,之后所有和客户通讯都是通过这个套接字
  39. hSock, //服务 器套接字
  40. (struct sockaddr*)&clientaddr, //客户端地址
  41. &addrlen); //地址大小
  42. // char sipaddr[100];
  43. char sipaddr[100];
  44. //将数字转换成ip地址字符串]
  45. inet_ntop(AF_INET,&clientaddr.sin_addr,sipaddr,100);
  46. printf("有客户连接:[%s]:%d\n",sipaddr,ntohs(clientaddr.sin_port));
  47. //5、收发数据 send/recv
  48. char buff[1024]={"hello client!\n"};
  49. send(
  50. clientsock, //客户套接字
  51. buff, //数据包
  52. strlen(buff)+1, //数据长度
  53. 0 //默认0
  54. );
  55. recv( //接收客户消息,阻塞
  56. clientsock,
  57. buff,
  58. 1024,
  59. 0
  60. );
  61. printf("接收到客户 %s:%d 内容:%s\n",sipaddr,ntohs(clientaddr.sin_port),buff);
  62. //6、关闭套接字 close
  63. close(hSock);
  64. close(clientsock);
  65. return 0;
  66. }

Linux网络通信流程-UDP

image.png

服务端

  1. #include <sys/types.h> // 类型定义
  2. #include <sys/socket.h> //提供网络通信函数
  3. #include<unistd.h> //针对系统调用的封装fork,pipe read write 等
  4. #include<netinet/in.h> // 互联网地址族定 义数据结构sockaddr_ in
  5. # include<arpa/inet.h> //提供IP地址转换函数
  6. #include<stdio.h>
  7. #include<string.h>
  8. // UDP编程
  9. // 1.创建套接字
  10. // 2. 绑定
  11. // 3.接收消息
  12. // 4. 发消息
  13. // 5.关闭套接字
  14. int main(){
  15. // 1.创建套接字
  16. int sock = socket(AF_INET,SOCK_DGRAM, IPPROTO_UDP);
  17. // 2.綁定
  18. struct sockaddr_in saddr;
  19. inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr);//填写服务器ip地址192.168.78.130
  20. saddr.sin_port = htons(12345); //主机字节序转换成网络字节序,服务端口
  21. saddr.sin_family = AF_INET; //网络协议
  22. int addrlen = sizeof(saddr); //地址大小
  23. bind(sock,(struct sockaddr*)&saddr,addrlen);
  24. printf("wait client connect ...");
  25. // 3.接收消息
  26. char buff[1024] = {};
  27. struct sockaddr_in clientaddr = {}; //客户地址
  28. recvfrom(
  29. sock, //套接字
  30. buff, //缓冲区
  31. 1024, //缓冲区大小
  32. 0, //标志,默认0
  33. (struct sockaddr*)&clientaddr, //接收客户地址,之后用这个地址给客户发消息
  34. &addrlen //地址长度
  35. );
  36. char sipaddr[100];
  37. //将数字转换成ip地址字符串]
  38. inet_ntop(AF_INET,&clientaddr.sin_addr,sipaddr,100);
  39. printf("有客户连接:[%s]:%d 内容是:%s\n",sipaddr,ntohs(clientaddr.sin_port),buff);
  40. // 4. 发消息
  41. sendto(
  42. sock,
  43. "hello 客户端!",
  44. 18,
  45. 0,
  46. (struct sockaddr*)&clientaddr,
  47. addrlen
  48. );
  49. // 5.关闭套接字
  50. close(sock);
  51. }

客户端

  1. #include <sys/types.h> // 类型定义
  2. #include <sys/socket.h> //提供网络通信函数
  3. #include<unistd.h> //针对系统调用的封装fork,pipe read write 等
  4. #include<netinet/in.h> // 互联网地址族定 义数据结构sockaddr_ in
  5. # include<arpa/inet.h> //提供IP地址转换函数
  6. #include<stdio.h>
  7. #include<string.h>
  8. // UDP编程
  9. // 1.创建套接字
  10. // 2.发消息
  11. // 3.接收消息
  12. // 5.关闭套接字
  13. int main(){
  14. // 1.创建套接字
  15. int sock = socket(AF_INET,SOCK_DGRAM, IPPROTO_UDP);
  16. // 2.发消息
  17. struct sockaddr_in saddr;
  18. inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr);//填写服务器ip地址192.168.78.130
  19. saddr.sin_port = htons(12345); //主机字节序转换成网络字节序,服务端口
  20. saddr.sin_family = AF_INET; //网络协议
  21. int addrlen = sizeof(saddr); //地址大小
  22. //发消息给服务端
  23. sendto(
  24. sock,
  25. "hello 服务器!",
  26. 18,
  27. 0,
  28. (struct sockaddr*)&saddr,
  29. addrlen
  30. );
  31. printf("发送成功!\n");
  32. // 3.接收消息
  33. char buff[1024] = {};
  34. recvfrom(
  35. sock, //套接字
  36. buff, //缓冲区
  37. 1024, //缓冲区大小
  38. 0, //标志,默认0
  39. (struct sockaddr*)&saddr, //接收服务端地址
  40. &addrlen //地址长度
  41. );
  42. printf("接到服务断消息:%s\n",buff);
  43. // 5.关闭套接字
  44. close(sock);
  45. }

image.png