SOCKET网络编程知识点

109 阅读3分钟

SOCKET网络编程笔记

1.Internet套接字有哪些类型

流格式套接字(SOCK_STREAM)与数据报格式套接字(SOCK_DARAM)

流格式套接字有以下几个特征:

  • 数据在传输过程中不会消失(基于TCP协议)
  • 数据是按照顺序传输的
  • 数据的发送和接收是不同步的

数据报格式套接字有以下几个特征:

  • 强调快速传输而非传输顺序
  • 传输的数据可能丢失和损毁(基于UDP协议)
  • 限制每次传输的数据大小
  • 数据的接收和发送是同步的(换句话说,接受次数和发送次数相同)

2.OSI网络七层模型

OSI网络模型把通信工作分为7层:从下到上分别是物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

后来简化为4层,从下到上分别是接口层、网络层、传输层和应用层,这就是大名鼎鼎的TCP/IP模型。

image.png

3.TCP数据报结构三次握手

三次握手可以形象的比喻下面这一段话:

  • [Shake 1] 套接字A:“你好,套接字B,我这里有数据要传送给你,建立连接吧。”
  • [Shake 2] 套接字B:“好的,我这边已准备就绪。”
  • [Shake 3] 套接字A:“谢谢你受理我的请求。”

三次握手的关键是要确认对方收到了自己的数据包,这个目标就是通过“确认号(Ack)”字段实现的。计算机会记录下自己发送的数据包序号 Seq,待收到对方的数据包后,检测“确认号(Ack)”字段,看Ack = Seq + 1是否成立,如果成立说明对方正确收到了自己的数据包。

image.png

4.TCP四次挥手断开连接

断开连接需要四次挥手,可以形象的比喻为下面的对话:

  • [Shake 1] 套接字A:“任务处理完毕,我希望断开连接。”
  • [Shake 2] 套接字B:“哦,是吗?请稍等,我准备一下。”
  • 等待片刻后……
  • [Shake 3] 套接字B:“我准备好了,可以断开连接了。”
  • [Shake 4] 套接字A:“好的,谢谢合作。”

image.png

5.Linux下的socket演示程序

服务器端代码server.cpp

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(){
    //创建套接字
    int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    //将套接字和IP、端口绑定
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充
    serv_addr.sin_family = AF_INET; //使用IPv4地址
     serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址
     serv_addr.sin_port = htons(1234); //端口
     bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

     //进入监听状态,等待用户发起请求
     listen(serv_sock, 20);

      //接收客户端请求
      struct sockaddr_in clnt_addr;
      socklen_t clnt_addr_size = sizeof(clnt_addr);
      int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

      //向客户端发送数据
      char str[] = "http://c.biancheng.net/socket/";
      write(clnt_sock, str, sizeof(str));

      //关闭套接字
      close(clnt_sock);
      close(serv_sock);

      return 0;
    
}

大家需要记住127.0.0.1,它是一个特殊IP地址,表示本机地址,后面会经常用到。 客户端代码client.cpp


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

int main(){
    //创建套接字
    int sock = socket(AF_INET, SOCK_STREAM, 0);

    //向服务器(特定的IP和端口)发起请求
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
    serv_addr.sin_family = AF_INET;  //使用IPv4地址
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    serv_addr.sin_port = htons(1234);  //端口
    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
   
    //读取服务器传回的数据
    char buffer[40];
    read(sock, buffer, sizeof(buffer)-1);
   
    printf("Message form server: %s\n", buffer);
   
    //关闭套接字
    close(sock);

    return 0;
}