网络:3.Socket编程TCP

Socket编程TCP

一.接口补充

1. listen(系统调用)

作用:
将一个主动套接字(客户端用的 socket)转换为被动套接字,使其可以接受来自客户端的连接请求。(常用于 TCP 服务器端,UDP 无需调用该函数)

函数原型

cpp 复制代码
#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd, int backlog);
  • 参数

    • sockfd:TCP 套接字文件描述符
    • backlog:未完成连接队列(半连接队列) 的最大长度;表示允许系统为该监听 socket 同时排队的最大连接请求数;超过该值的连接请求将被丢弃;
  • 返回值

    • 成功: 0
    • 失败: -1,并设置 errno

2. accept(系统调用)

作用:从已完成连接队列中取出一个已建立的客户端连接,生成一个新的套接字用于与该客户端通信 (常用于 TCP 服务器端;UDP 无连接,不需要调用此函数).

函数原型

cpp 复制代码
#include <sys/types.h>
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//没有连接就会阻塞卡在这里
  • 参数

    • sockfd:服务器端用于监听的套接字文件描述符(必须已调用bind和listen);
    • addr(输出型参数):
      • 指向一个 struct sockaddr_in 结构体的指针,用于保存已连接客户端的地址信息(IP + 端口);
      • 若不关心客户端地址,可填 NULL
    • addrlen(输出型参数):
      • 指向一个 socklen_t 类型变量的指针,初始时应设置为 sizeof(struct sockaddr_in)
      • 函数返回时,会被修改为实际的地址结构长度。
  • 返回值

    • 成功: 返回一个新的套接字文件描述符(用于与客户端通信);
    • 失败: 返回 -1,并设置errno。

3. connect(系统调用)

作用: 用于客户端向服务器发起连接请求; 当服务器端调用了 listen() 并处于监听状态后,客户端使用 connect() 来建立 TCP 连接(三次握手);(常用于 TCP 客户端;UDP 客户端也可调用该函数以指定默认通信目标地址.)

函数原型

cpp 复制代码
#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 参数

    • sockfd:套接字文件描述符;
      • 通常是:socket(AF_INET, SOCK_STREAM, 0)(TCP);
      • 对于 UDP(SOCK_DGRAM),调用 connect 并不会真正建立连接,而是指定默认的目标地址。
    • addr: 指向服务器端地址结构体的指针(struct sockaddr_in server; 使用时需强制类型转换为 struct sockaddr*);
    • addrlen:地址结构体的大小,sizeof(struct sockaddr_in)
  • 返回值

    • 成功: 0
    • 失败: -1,并设置 errno
  • 注:

    client会在connect成功之后,在底层自动进行bind!


4. popen(库函数)

作用:
创建一个管道,与一个子进程之间建立单向通信通道,并通过该子进程执行指定的命令(通常是 shell 命令)。

它相当于同时调用了 fork() + pipe() + exec(),让父进程可以像读写文件一样与命令交互。

函数原型

cpp 复制代码
#include <stdio.h>

FILE *popen(const char *command, const char *type);
  • 参数

    • **command:**要执行的 shell 命令字符串,例如 "ls -l", "cat /etc/passwd" 等;
      • 实际上会调用 /bin/sh -c command 来执行;
      • 因此几乎所有命令行都可以写在这里。
    • type: 打开管道的模式
      • "r":从命令的标准输出(stdout) 读取数据(父进程读,子进程写);一般用这个
      • "w":向命令的标准输入(stdin) 写入数据(父进程写,子进程读)。
  • 返回值

    • 成功: 返回一个 FILE* 类型的文件流指针;
    • 失败: 返回 NULL,并设置 errno
  • 注意事项

    管道使用完毕后,必须调用:

    cpp 复制代码
    int pclose(FILE *stream);

    来关闭管道并等待子进程结束(否则会产生僵尸进程)。

二.命令补充

1. telnet

作用:用于测试服务器端口是否可连通、是否在监听, 常用于验证TCP服务是否正常工作, 它通过建立 TCP 连接的方式模拟客户端访问。

命令格式

shell 复制代码
telnet [主机名或IP地址] [端口号]
  • 返回结果说明
情况 输出提示 含义
成功连接 Connected to xxx.xxx.xxx.xxx 说明端口已开放且可通信
连接失败 Connection refused 端口未被监听被防火墙拦截**
超时 Connection timed out 网络不可达 / 服务器无响应
未解析 Unknown host 域名错误或 DNS 无法解析
  • 按下:Ctrl + ], 回车,开始输入
  • 然后输入:quit,退出
  • 或再按下Ctrl + ], 回车,退出。

三.知识补充

1. TCP 服务器中 listen 和 accept 的分工关系:

  • listen 的socket(_listensockfd)
    就像"店员张三在门口拉客",只负责等待并接受新的连接请求 (即负责"拉人进来")。
    它本身不提供服务,不进行读写操作。
  • accept 返回的新socket(sockfd)
    就像张三把客人带进来后,交给店里的人(李四、王五、赵六)去"提供具体服务"。
    每个客户端连接都会生成一个新的 socket,用于 读写数据(I/O 服务)
相关推荐
AORO20254 小时前
智能三防手机哪款好?22000mAh+夜视+露营灯打造专业户外装备
服务器·网络·智能手机·电脑·1024程序员节
Hello.Reader4 小时前
Data Sink定义、参数与可落地示例
java·前端·网络
报错小能手7 小时前
计算机网络自顶向下方法36——网络层 网络地址转换 网络安全(防火墙、入侵检测系统)
网络·计算机网络·智能路由器
研究司马懿7 小时前
【ETCD】ETCD常用命令
网络·数据库·云原生·oracle·自动化·运维开发·etcd
西部森林牧歌8 小时前
Arbess零基础学习 - 使用Arbess+GitLab实现PHP项目构建/主机部署
ci/cd·gitlab·php·tiklab devops
张人玉8 小时前
网络通讯TCP和UDP的区别
网络协议·tcp/ip·udp
独行soc8 小时前
2025年渗透测试面试题总结-234(题目+回答)
网络·python·安全·web安全·渗透测试·1024程序员节·安全狮
上海云盾安全满满9 小时前
APP应用怎么选择游戏盾
网络·游戏
打不了嗝 ᥬ᭄9 小时前
数据链路层
linux·网络·网络协议·http
Fanmeang10 小时前
无线交换机(AC)核心技术详解:构建集中式Wi-Fi网络的基石
网络