Socket 函数详细讲解(Socket编程步骤、socket函数、TCP和UDP的区别)

Socket 函数详细讲解和 C++ 示例

  • 一、 Socket 基本概念
    • 1. Socket 简介
    • 2. Socket 编程步骤
    • 3. TCP Socket 编程示例
      • 服务器端
      • 客户端
    • 4. 详细说明
  • 二、 socket 函数
    • 1. domain 通讯的协议家族
    • 2. type 数据传输的类型
    • 3. protocol 最终使用的协议
      • 返回值
      • 示例
  • 三、TCP 和 UDP的区别
    • 1. TCP(传输控制协议)
    • 2. UDP(用户数据报协议)
    • 3. 总结
    • 示例应用

一、 Socket 基本概念

1. Socket 简介

Socket 是一种通信机制,允许在不同主机之间或同一主机的不同进程之间进行数据交换。使用 socket 编程可以实现 TCP 和 UDP 协议的网络通信。

2. Socket 编程步骤

  1. 创建 Socket
  2. 绑定(仅服务器)
  3. 监听(仅服务器)
  4. 接受连接(仅服务器)
  5. 连接服务器(仅客户端)
  6. 发送和接收数据
  7. 关闭 Socket

3. TCP Socket 编程示例

服务器端

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>#define PORT 8080
#define BUFFER_SIZE 1024int main() {int server_fd, new_socket;struct sockaddr_in address;int addrlen = sizeof(address);char buffer[BUFFER_SIZE] = {0};// 创建 socket 文件描述符if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}// 绑定address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");close(server_fd);exit(EXIT_FAILURE);}// 监听if (listen(server_fd, 3) < 0) {perror("listen failed");close(server_fd);exit(EXIT_FAILURE);}// 接受连接if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {perror("accept failed");close(server_fd);exit(EXIT_FAILURE);}// 读取客户端发送的数据read(new_socket, buffer, BUFFER_SIZE);std::cout << "Message from client: " << buffer << std::endl;// 发送数据给客户端const char *message = "Hello from server";send(new_socket, message, strlen(message), 0);std::cout << "Hello message sent\n";// 关闭 socketclose(new_socket);close(server_fd);return 0;
}

客户端

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>#define PORT 8080
#define BUFFER_SIZE 1024int main() {int sock = 0;struct sockaddr_in serv_addr;char buffer[BUFFER_SIZE] = {0};// 创建 socket 文件描述符if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {std::cerr << "Socket creation error" << std::endl;return -1;}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(PORT);// 将地址转换成二进制if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {std::cerr << "Invalid address/ Address not supported" << std::endl;return -1;}// 连接服务器if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {std::cerr << "Connection Failed" << std::endl;return -1;}// 发送数据给服务器const char *message = "Hello from client";send(sock, message, strlen(message), 0);std::cout << "Hello message sent\n";// 读取服务器发送的数据read(sock, buffer, BUFFER_SIZE);std::cout << "Message from server: " << buffer << std::endl;// 关闭 socketclose(sock);return 0;
}

4. 详细说明

  1. 创建 Socket

    • socket(int domain, int type, int protocol)
      • domain: 使用的协议族,例如 AF_INET 表示 IPv4 网络协议。
      • type: Socket 类型,例如 SOCK_STREAM 表示面向连接的 TCP。
      • protocol: 一般设置为 0,让系统自动选择合适的协议。
  2. 绑定

    • bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
      • 将 socket 绑定到特定的 IP 地址和端口号。
  3. 监听

    • listen(int sockfd, int backlog)
      • 使 socket 处于监听状态,准备接受连接。
      • backlog 指定等待连接队列的最大长度。
  4. 接受连接

    • accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
      • 从监听队列中接受一个连接,返回一个新的 socket 文件描述符,用于与客户端通信。
  5. 连接服务器

    • connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
      • 客户端使用这个函数连接到服务器。
  6. 发送和接收数据

    • send(int sockfd, const void *buf, size_t len, int flags)
    • recv(int sockfd, void *buf, size_t len, int flags)
    • readwrite 也可以用于接收和发送数据。
  7. 关闭 Socket

    • close(int sockfd)
      • 关闭 socket 文件描述符。

二、 socket 函数

  • socket(int domain, int type, int protocol)
    • domain: 使用的协议族,例如 AF_INET 表示 IPv4 网络协议。
    • type: Socket 类型,例如 SOCK_STREAM 表示面向连接的 TCP。
    • protocol: 一般设置为 0,让系统自动选择合适的协议。

1. domain 通讯的协议家族

  • PF_INET IPv4互联网协议族。
  • PF_INET6 IPv6互联网协议族。
  • PF_LOCAL 本地通信的协议族。
  • PF_PACKET 内核底层的协议族。
  • PF_IPX IPX Novell协议族。

IPv6尚未普及,其它的不常用。

2. type 数据传输的类型

  • SOCK_STREAM 面向连接的socket:
    -----1)数据不会丢失;2)数据的顺序不会错乱;3)双向通道。
  • SOCK_DGRAM 无连接的socket:
    -----1)数据可能会丢失;2)数据的顺序可能会错乱;3)传输的效率更高。

3. protocol 最终使用的协议

protocol:协议类型

  • 通常为 0,表示自动选择与指定域和类型匹配的协议。
  • 对于 AF_INETSOCK_STREAM,默认为 IPPROTO_TCP
  • 对于 AF_INETSOCK_DGRAM,默认为 IPPROTO_UDP

返回值

  • 成功时返回一个新的套接字描述符。
  • 失败时返回 -1,并设置 errno 以指示错误类型。

示例

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {perror("socket failed");exit(EXIT_FAILURE);
}

在IPv4网络协议家族中,数据传输方式为SOCK_STREAM的协议只有IPPROTO_TCP,数据传输方式为SOCK_DGRAM的协议只有IPPROTO_UDP

本参数也可以为0

socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);    // 创建tcp的sock
socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);    // 创建udp的sock

三、TCP 和 UDP的区别

TCP(传输控制协议)和UDP(用户数据报协议)是两种主要的传输层协议,用于网络通信。它们有各自的优缺点和适用场景。

1. TCP(传输控制协议)

  1. 连接导向

    • TCP是面向连接的协议,在传输数据之前需要建立连接(三次握手)。
    • 连接建立后,双方可以进行可靠的数据传输。
  2. 可靠性

    • 提供可靠的数据传输,确保数据包按顺序到达并且没有丢失或重复。
    • 使用确认机制、重传机制和校验和来保证数据的完整性和正确性。
  3. 流量控制

    • 具有流量控制和拥塞控制机制,防止网络拥塞和发送方发送速度过快。
    • 使用滑动窗口协议来管理流量控制。
  4. 传输速度

    • 由于其可靠性和流量控制机制,TCP的传输速度相对较慢,但可靠性高。
  5. 头部开销

    • TCP头部较大,通常为20字节(不包括可选字段)。
  6. 适用场景

    • 适用于需要高可靠性的数据传输场景,如网页浏览(HTTP/HTTPS)、文件传输(FTP)、电子邮件(SMTP)、远程登录(SSH)等。

2. UDP(用户数据报协议)

  1. 无连接

    • UDP是无连接的协议,在传输数据之前不需要建立连接。
    • 数据包独立发送,无需维护连接状态。
  2. 不可靠性

    • 提供不可靠的数据传输,不保证数据包的顺序、无丢失和无重复。
    • 发送数据后不确认是否到达目的地,不重传丢失的数据包。
  3. 无流量控制

    • UDP没有流量控制和拥塞控制机制,发送速度完全取决于应用程序。
  4. 传输速度

    • 由于没有连接建立、流量控制和重传机制,UDP的传输速度较快,但可靠性低。
  5. 头部开销

    • UDP头部较小,固定为8字节。
  6. 适用场景

    • 适用于对传输速度要求高但对可靠性要求不高的场景,如视频直播、在线游戏、实时语音通话(VoIP)、广播通信等。

3. 总结

特性TCPUDP
连接性面向连接(需要三次握手)无连接
可靠性可靠传输,保证顺序和完整性不可靠传输,不保证顺序和完整性
流量控制有流量控制和拥塞控制无流量控制和拥塞控制
传输速度较慢较快
头部开销较大(20字节,不包括可选字段)较小(8字节)
适用场景需要高可靠性的应用需要高速度的应用

示例应用

  • TCP:HTTP/HTTPS、FTP、SMTP、SSH、Telnet
  • UDP:DNS查询、DHCP、TFTP、在线游戏、视频流、实时音频

了解TCP和UDP的区别及其适用场景,可以帮助开发人员在实际网络编程中选择合适的传输层协议,以满足不同应用的需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/841099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序预览图片和H5使用canvas实现图片+蒙层+文字

1、效果 2.H5实现 <!--* Author: limingfang* Date: 2024-05-20 10:26:51* LastEditors: limingfang* LastEditTime: 2024-05-21 16:31:11* Description: --> <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8&q…

如何设计小程序的站内信功能

设计小程序的站内信功能&#xff0c;需要考虑用户体验、安全性、功能完整性等方面。以下是设计和实现站内信功能的详细步骤和细节&#xff1a; 目录 1. 需求分析2. 数据库设计用户表&#xff08;Users Table&#xff09;消息表&#xff08;Messages Table&#xff09;用户消息…

C++ | Leetcode C++题解之第112题路径总和

题目&#xff1a; 题解&#xff1a; class Solution { public:bool hasPathSum(TreeNode *root, int sum) {if (root nullptr) {return false;}if (root->left nullptr && root->right nullptr) {return sum root->val;}return hasPathSum(root->left…

Java的类和对象

Java的类和对象 前言一、面向过程和面向对象初步认识C语言Java 二、类和类的实例化基本语法示例注意事项 类的实例化 三、类的成员字段/属性/成员变量注意事项默认值规则字段就地初始化 方法static 关键字修饰属性代码内存解析 修饰方法注意事项静态方法和实例无关, 而是和类相…

变量的命名规则

必须遵守的规则 不能重名不能以数字开头不能使用升序关键字命名不能有特殊符号&#xff08;下划线除外&#xff09; 建议的命名规则&#xff1a;变量名要有含义——>用英文&#xff08;拼音&#xff09;表示变量的作用 非常不建议的命名规则&#xff1a;用汉字命名 常用命…

AI早班车5.25

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

题解:CF859C Pie Rules

Luogu - CF859C Analysis 由题意知每个人选择时都是以最佳情况来选&#xff0c;最佳情况是指他的选择能使后面拿的更多。所以决定最佳情况是来自后面。 还有一个重要性质&#xff0c;不管是 Bob 还是 Alice&#xff0c;只要是拥有决策权的人面对同一个局面&#xff0c;其得到…

Bazel编译Android程序

一、编译C程序 1、在项目根目录的WROKSPACE文件添加以下配置 //WORKSPACE文件 load("bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive(name "rules_android_ndk",sha256 "b1a5ddd784e6ed915c2035c0db536a…

C# 拓展方法(涉及Linq)

拓展方法 定义一个扩展方法使用扩展方法例如再举个例子终极例子 注意事项与Linq 在C#中&#xff0c;扩展方法是一种特殊的静态方法&#xff0c;允许开发者向现有类型“添加”新的方法&#xff0c;而无需修改该类型的源代码或创建新的派生类型。这种机制提供了一种更为灵活的方式…

OpenGL给定直线起点和终点不同的颜色,使用中点Bresenham画线

用鼠标左键按下确定直线起点&#xff0c;鼠标左键抬起确定直线终点。放一部分代码。 // 中点Bresenham算法.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <GL/glut.h> #include <iostream> #include <cmath>int windowWidt…

Linux更改系统中的root密码

Linux里面的root密码忘记了怎么办&#xff1f; 1 更改系统中的 root 密码 &#xff08;1&#xff09;键盘 CtrlAltT 快捷键打开终端。 &#xff08;2&#xff09;在终端窗口中输入以下代码&#xff1a; sudo passwd root &#xff08;3&#xff09;输入锁屏密码 &#xf…

解决本地环境正常但Linux服务器上Gson日期解析失败的问题

问题背景 在软件开发过程中&#xff0c;本地环境与服务器环境之间的差异可能导致意外的运行时错误。本文将探讨一个常见的问题&#xff1a;在本地环境中使用 Gson 库解析 JSON 数据时日期字段正常解析&#xff0c;但部署到 Linux 服务器上时却出现 JsonSyntaxException 错误。…

常见的授权场景及其实现方法

在微服务架构中处理授权时&#xff0c;通常考虑多种场景来保证系统的安全性和灵活性。这些场景涵盖了从简单的API权限验证到复杂的基于策略的访问控制。下面&#xff0c;我将详细介绍几种常见的授权场景及其实现方法。 文章目录 1. 简单的权限验证实现方法&#xff1a; 2. 细粒…

从0开始学统计-战斗机保护和代表性抽样

1.什么是抽样研究&#xff1f;为什么要做抽样研究&#xff1f; 抽样研究是一种研究方法&#xff0c;它涉及从整体人群或群体中选取一部分样本来代表整体&#xff0c;以进行研究和推断。在抽样研究中&#xff0c;研究者从总体中选择一个相对较小的样本&#xff0c;通过对这个样…

2024-05学习笔记

最近的学习大多都是和mysql的索引相关的 1.mvcc mvcc是不需要手动配置&#xff0c;是mysql的一个机制 在事务开启时&#xff0c;对涉及到的数据加一个隐藏列&#xff0c;隐藏列对应的值&#xff0c;就是事务id 如果当前是修改操作&#xff0c;就copy一份原来的数据到新的一行…

Topk问题以及二叉树的三种层序遍历和基本操作

一、Topk问题 1、问题描述 TOP-K问题&#xff1a;即求数据结合中前K个最大的元素或者最小的元素&#xff0c;一般情况下数据量都比较大。 比如&#xff1a;专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。 2、思路 对于Top-K问题&#xff0c;能想到的最简单直接的…

【npm如何使用以及常用的包npm包的用法】

npm&#xff08;Node Package Manager&#xff09;是Node.js的包管理工具&#xff0c;用于安装、卸载、更新和管理Node.js应用程序的依赖项。以下是npm的基本使用方法和一些常用npm包的用法&#xff1a; 一、npm的基本使用方法 安装npm&#xff1a;npm通常与Node.js一起安装。…

618快到了,送大家一款自动化脚本工具,一起薅羊毛

前言 一年一次的618活动来了&#xff0c;大家做好准备了&#xff0c;奇谈君为大家准备好用的618神器&#xff0c;解放双手&#xff0c;简单操作就可以把红包拿到手。 京淘自动助手 首次使用前需要进行设置 将手机的无障碍权限和悬浮窗权限打开 设置完成后&#xff0c;可以把…

什么是健康信息卡

健康档案信息卡是交由居民本人保管的个人健康信息卡片。 其内容包括&#xff1a;居民个人主要基本信息、健康档案编码、患有的重要疾病、过敏史以及紧急情况下的联系人及联系方式&#xff0c;还有所属基层医疗机构的责任医生、护士及联系电话等。它主要用于居民在复诊、转诊或接…

Android 14.0 系统多个播放器app时,设置默认播放器

1.概述 在14.0的系统产品开发中,对于在系统中有多个播放器的时候,这时候如果调用代码打开播放器,会出现多个播放器列表让用户选择启动哪个播放器,所以产品开发需求需要设置默认播放器,当打开播放器的时候,就直接打开播放器就可以了,所以就需要了解查询播放器列表流程,然…