socket编程(一) - 基本介绍

[复制链接]
查看831 | 回复6 | 2023-9-4 21:28:32 | 显示全部楼层 |阅读模式

每学习一个新的知识的时候,我们都会问这是什么?socket是什么?在各大搜索引擎搜索socket都会从插座给你介绍socket的起源。这些,都不重要!对我们来说,我们只需要知道socket就是可以用于网络设备互相通信的一个工具就可以,我们通常称socket为套接字,知道这些就够了。

写在前面

由于Linux有“一切皆文件”的特性,在socket编程这一块,Linux和Windows的实现是有所出入的,本系列文章默认以Linux为环境。实际上在嵌入式以及物联网领域,更多的还是以Linux为基础的。

socket系列文章大概会分为三篇:

  1. 基本介绍socket,了解什么是socket,了解socket的基本原理,了解都有哪些类型的socket。顺便会简单介绍IP、MAC和端口,最后写一个简单的socket demo。
  2. 接着上一节的socket demo中,深入分析socket常用的数据结构,接口函数等基础的语法知识。最后通过了解我最近在做的项目中对socket的使用,来更深入的了解socket的应用。
  3. socket的高级应用,包括文件传输,域名访问等等。最后会说一说socket中使用udp协议的一些内容。

基本原理

那么,从这里开始,我们正式的开始学习socket。

废话部分:这里我斟酌了很久,甚至写了删,删了再写,如此反复,我就在想,该如何简单的介绍socket通信的原理,让我自己明白,也能让看到这个文章的每一位朋友明白?我还是决定,从socket的分类说起。

socket的分类

由于底层实现的不同,其实socket的实现也是千差万别的。本片文章中主要说说,流式套接字和数据报式套接字吧。可以先说明结论:

  • 流式套接字(SOCK_STREAM):基于TCP协议实现,熟悉TCP协议的朋友都知道三次握手,这样做的目的是为了数据安全,同时也确保了数据的完整性。但是,这同时也带来了很明显的缺点,那就是慢。以上是流式套接字的特点,而针对流式套接字具体的传输方式,我想再具体说明,所谓流式套接字,就是数据在设备之间有顺序的传输,即“ABCDEFGHIJKLMN”, 必须是按照顺序传输的,不可能先收到B然后再收到A。这样做也是确保数据完整性和安全性的一种实现。
  • 数据报式套接字(SOCK_DGRAM):基于UDP协议实现,UDP协议可能在编程的过程中使用频率没有TCP协议那么高,UDP最明显的特点就是不需要进行三次握手,只管发送数据,至于客户端能否收到数据,我不管,数据完全与否我也不管。

在本次socket的学习中,主要以基于TCP协议的流式套接字,数据报,后面也会简单的涉及。

流式套接字收发流程

socket通信是CS架构的,服务端和客户端都需要做相应的配置,才能建立通信。在正式开始之前,我希望我们能先大概了解IP,MAC和Port之间的区别:

  • IP : 确定你的大体位置,也就是局域网所在位置
  • MAC: 确定你的设备是局域网中的哪台设备
  • Port: 确定需要连接的进程是设备中的哪一个

首先来看服务端

  1. 首先申请一个socket。

    在这里插一嘴,在Linux环境中,贯彻了一切皆文件的思想,所以这里的socket实际上也是一个文件,所以申请一个socket,相当于调用open()函数,生成了一个文件描述符,而接下来的所有操作,在底层逻辑上看来就是对文件的各种IO操作。

  2. 将申请到的socket与IP和Port绑定。

  3. 服务端开始监听该socket

  4. 服务端阻塞等到客户端连接

同时,另外一台设备,也就是客户端

  1. 申请一个socket。

    为什么客户端也要申请一个socket?上面我们提到了服务端创建的socket实际上就是一个文件,相关的操作也是对文件的操作,所以客户端新建一个socket,就是对服务端socket的一个承载。

  2. 配置要连接的IP和Port

  3. 连接

  4. 与服务端进行数据交互

  5. 交互完成之后关闭套接字

  6. 客户端流程结束

回到服务端,其实在实际的应用中,服务端的等到客户连接过程是循环等待的。对于程序而言,服务器端的socket资源在使用完毕之后也需要及时释放。

socket demo

最后,我们通过一个特别简单的demo来初次看一下socket的连接过程。

代码段:socket_demo.c

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

int server_socket()
{
    int server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  // 创建socket,返回值实际上就是一个fd

    struct sockaddr_in server_addr;  // 配置服务端IP和端口
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.10");
    server_addr.sin_port = htons(6666);
    bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));  // 将socket和IP以及端口绑定
    listen(server_socket, 20);  // 开始监听
    struct sockaddr_in client_addr;
    socklen_t client_addr_size = sizeof(client_addr);
    while (1) {
        // accept函数会阻塞等待客户端的连接,并返回客户端的socket
        int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_size);
        char str[] = "Hello Socket!";
        send(client_socket, str, sizeof(str), 0);  // 发送Hello Socket给客户端  
        close(client_socket);
    }
    close(server_socket);
    return 0;
}


int client_socket()
{
    int client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.10");
    server_addr.sin_port = htons(6666);
    connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));

    char buffer[15];
    recv(client_socket, buffer, 15, 0);
    printf("Message form server: %s\n", buffer);

    close(client_socket);
    return 0;
}

代码段:common.h

#ifndef _COMMON_H
#define _COMMON_H

extern int server_socket();
extern int client_socket();

#endif  /* _COMMON_H */

上面的demo中,展现了一个socket最基本的连接过程,虽然是最近本的,但是更多高级的,重要的socket用法,都是从基本方法派生的。下一篇文章将,自己讲讲上面每一个函数的具体含义,同时分享我最近项目中需要使用的socket需求。

回复

使用道具 举报

夜樱99 | 2023-9-4 22:27:11 | 显示全部楼层
学习了!
回复

使用道具 举报

jkernet | 2023-9-5 07:56:21 来自手机 | 显示全部楼层
好文章点赞
回复 支持 反对

使用道具 举报

爱笑 | 2023-9-5 08:23:12 | 显示全部楼层
可乐高产~
用心做好保姆工作
回复

使用道具 举报

ai_mcu | 2023-9-5 08:54:20 | 显示全部楼层
之前接触过忘差不多了,再跟着大佬走一遍
明天总会更好
回复 支持 反对

使用道具 举报

Mr.Tail | 2023-9-5 08:55:51 | 显示全部楼层
好详细
回复

使用道具 举报

开发板 | 2023-9-7 08:53:26 | 显示全部楼层
太强了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则