网络: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 服务)
相关推荐
sailing-data4 分钟前
【SE 网络】无线物联网络如何选
网络
skyyx20028 分钟前
写给网工新手:子网掩码基本概念和一些计算方法
运维·网络
JY.yuyu9 分钟前
OSPF路由协议
网络
kiiila10 分钟前
【网络】网络通信模型
网络
2501_9159184119 分钟前
TCP 抓包分析在复杂网络问题中的作用,从连接和数据流层面理解系统异常行为
网络·网络协议·tcp/ip·ios·小程序·uni-app·iphone
隔壁小白21 分钟前
PHP 8.1 枚举(Enums)详解
php
while(1){yan}1 小时前
基础IP协议知识
网络·网络协议·tcp/ip
车载测试工程师1 小时前
CAPL学习-AVB交互层-功能函数-控制类函数
学习·tcp/ip·以太网·capl·canoe
Turboex邮件分享2 小时前
邮件系统中的消息排队与调度机制分析
网络
郑州光合科技余经理2 小时前
海外国际版同城服务系统开发:PHP技术栈
java·大数据·开发语言·前端·人工智能·架构·php