首页 > 系统相关 >Linux----网络通信

Linux----网络通信

时间:2025-03-01 23:23:55浏览次数:6  
标签:网络通信 addr AF int ---- 地址 Linux 接字 include

一、IP地址详解

(一)核心概念

概念说明
IP地址网络设备的唯一逻辑标识符,相当于网络世界的"门牌号"
主机任何接入网络的终端设备(计算机/手机/服务器等)
核心作用① 设备标识 ② 路由寻址 ③ 数据传输

(二)技术特性

1. 基础结构

         32位IPv4地址结构
+----------------+----------------+
|   网络号        |    主机号       |
+----------------+----------------+
2. 关键组成
组成部分作用
网络号标识所属网络(类似城市+街道)
主机号标识具体设备(类似门牌号)

3. 存储方式

  • 数值形式:32位无符号整数(范围:0 ~ 2³²-1)
  • 存储格式:大端序(Big-Endian)
    // 示例:192.168.1.1的存储方式
    0xC0 (192) 0xA8 (168) 0x01 (1) 0x01 (1)
    

(三)地址分类(经典分类)

1. 类型划分

类别首位格式网络号范围主机号范围典型示例
A类0XXXXXXX前8位后24位1.0.0.1 ~ 126.255.255.254
B类10XXXXXX前16位后16位128.0.0.1 ~ 191.255.255.254
C类110XXXXX前24位后8位192.0.0.1 ~ 223.255.255.254
D类1110XXXX组播地址224.0.0.0 ~ 239.255.255.255
E类1111XXXX保留地址240.0.0.0 ~ 255.255.255.254

2. 特殊地址

地址类型范围用途
私有地址10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16局域网内部使用
环回地址127.0.0.0/8本机测试
自动配置地址169.254.0.0/16DHCP失败时临时使用

(四)现代划分方式(CIDR)

1. 表示方法

格式:IP地址/前缀长度
示例:192.168.1.0/24
  • 前缀长度:网络号的位数(范围:0-32)
  • 子网掩码:网络号全1,主机号全0
    /24 → 255.255.255.0
    /16 → 255.255.0.0
    

2. 地址计算示例

给定地址:192.168.1.100/24

网络地址:192.168.1.0    (IP & 子网掩码)
广播地址:192.168.1.255  (网络地址 | 主机位全1)
可用主机范围:192.168.1.1 ~ 192.168.1.254
最大主机数:2^8 - 2 = 254

(五)协议版本对比

特性IPv4IPv6
地址长度32位128位
地址表示点分十进制(192.168.1.1)冒号分隔十六进制(2001:db8::1)
地址空间约42.9亿3.4×10³⁸
包头复杂度简单扩展头部机制

二、OSI七层模型(理论框架)

OSI层级名称核心功能典型协议/技术数据单元
7应用层用户接口与应用服务HTTP、FTP、SMTP、DNS消息(Message)
6表示层数据格式转换、加密/解密、压缩SSL/TLS、JPEG、ASCII、GZIP
5会话层建立/管理/终止会话连接RPC、PPTP、NetBIOS
4传输层端到端连接、流量控制TCP、UDP、SCTP段(Segment)
3网络层寻址与路由选择IP、ICMP、NAT、OSPF包(Packet)
2数据链路层帧封装、MAC地址访问、差错校验Ethernet、PPP、VLAN、ARP帧(Frame)
1物理层比特流传输、物理介质规范RS-232、1000BASE-T、Wi-Fi比特(Bit)

关键技术示例:

应用层:浏览器访问网页时使用的HTTP协议
表示层:HTTPS通信中的TLS加密过程
会话层:VPN连接使用的PPTP协议
传输层:TCP的三次握手建立连接
网络层:路由器使用OSPF协议计算最优路径
数据链路层:交换机的MAC地址表学习
物理层:光纤传输的激光信号调制

(二)TCP/IP四层模型(实际标准)

TCP/IP层级对应OSI层核心功能典型协议设备示例
应用层5-7整合应用服务与网络接口HTTP、DNS、SMTP、MQTT网关设备
传输层4端到端数据传输管理TCP、UDP、QUIC负载均衡器
网络层3数据包路由与地址管理IP、ICMP、BGP、IPSec路由器
网络接口层1-2物理连接与本地网络传输Ethernet、Wi-Fi、PPP交换机/网卡
协议栈工作流程:
sequenceDiagram
    应用层->>传输层: 封装应用数据(如HTTP请求)
    传输层->>网络层: 添加TCP头+端口号
    网络层->>网络接口层: 添加IP头+IP地址
    网络接口层->>物理介质: 封装帧头+MAC地址

(三)关键对比分析

对比维度OSI模型TCP/IP模型
设计定位理论参考模型实际应用标准
层间关系严格分层松散分层
协议支持未绑定具体协议绑定TCP/IP协议族
普及程度主要用于教学互联网实际标准
地址管理网络层独立寻址IP地址统一寻址
校验机制每层独立校验端到端校验为主

(四)核心协议详解

1. 帧结构示例(Ethernet II)

+---------------+---------------+-----------------+---------------+
| 目标MAC(6B)   | 源MAC(6B)     | 类型(2B)        | 数据(46-1500B)| FCS(4B)       |
+---------------+---------------+-----------------+---------------+

2. IP数据包分片

原始包:总长度5000B(超过MTU 1500B)
分片1:1480B数据 + 20B头(偏移0,MF=1)
分片2:1480B数据 + 20B头(偏移185,MF=1)
分片3:40B数据 + 20B头(偏移370,MF=0)

3. TCP连接管理

三次握手:
Client → SYN → Server
Client ← SYN+ACK ← Server
Client → ACK → Server

四次挥手:
Client → FIN → Server
Client ← ACK ← Server
Client ← FIN ← Server
Client → ACK → Server

三、客户端/服务器(C/S)模型与传输协议详解

(一)C/S架构核心特性

特性说明
角色划分客户端(请求方)与服务端(响应方)
通信模式1:N 服务模式(单个服务端服务多个客户端)
网络依赖基于网络协议栈实现远程通信
协议支持可基于TCP/UDP等不同传输层协议实现

(二)TCP协议深度解析

1. 核心特性

graph TD
    A[面向连接] --> B[三次握手建立连接]
    A --> C[四次挥手断开连接]
    D[可靠传输] --> E[序列号机制]
    D --> F[确认应答机制]
    D --> G[超时重传机制]
    H[字节流模式] --> I[无边界数据流]
    H --> J[数据顺序保证]

2. 协议头结构(20字节基础头)

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------------------------------+---------------+-----------------+
|         源端口               |       目标端口                |
+-------------------------------+---------------+-----------------+
|                       序列号(SEQ)                           |
+---------------------------------------------------------------+
|                     确认号(ACK)                            |
+-----+---------+-----+-----------------------------------------+
|首部长度| 保留 |控制位|                 窗口大小                |
+-----+---------+-----+-----------------------------------------+
|        校验和        |          紧急指针(URG)                |
+---------------------+-----------------------------------------+

3. 典型应用场景

1. Web服务(HTTP/HTTPS)
2. 文件传输(FTP/SFTP)
3. 电子邮件(SMTP/POP3)
4. 数据库连接(MySQL/Oracle)
5. 远程登录(SSH/Telnet)

(三)UDP协议深度解析

1. 核心特性

graph TD
    A[无连接] --> B[无需建立连接]
    C[不可靠传输] --> D[无确认机制]
    C --> E[可能丢包]
    F[数据报模式] --> G[独立数据包]
    F --> H[保留边界]

2. 协议头结构(8字节固定头)

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------------------------------+---------------+-----------------+
|         源端口               |       目标端口                |
+-------------------------------+---------------+-----------------+
|           数据长度           |           校验和              |
+-------------------------------+---------------+-----------------+

3. 典型应用场景

1. 实时视频/音频传输(Zoom/WebRTC)
2. DNS域名解析
3. 网络监控(SNMP)
4. 物联网通信(MQTT-SN)
5. 在线游戏(部分实时对战)


(四)协议对比分析

对比维度TCPUDP
连接方式面向连接(三次握手)无连接
可靠性可靠传输(确认+重传)尽最大努力交付
数据边界字节流(无边界)数据报(保留边界)
传输效率较低(有连接开销)较高(无控制开销)
头部开销20-60字节固定8字节
拥塞控制完善机制(滑动窗口等)无控制
适用场景需可靠传输的应用实时性要求高的应用

四、socket() 函数详解

(一)函数原型

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

(二)核心功能

  • 创建通信端点:在内核中创建套接字数据结构
  • 分配资源:建立协议控制块(PCB)
  • 返回描述符:类似文件描述符的操作接口

(三)参数详解

1. domain(地址族)
常用值说明典型应用
AF_INETIPv4网络协议互联网通信(TCP/IP)
AF_INET6IPv6网络协议下一代互联网通信
AF_UNIX本地通信(文件系统路径)同主机进程间高效通信
AF_PACKET底层包接口网络嗅探器、协议分析工具

注意AF_*(地址族)与PF_*(协议族)在Linux中已统一,但推荐使用AF_前缀

2. type(套接字类型)
类型标志特性对应协议
SOCK_STREAM面向连接、可靠传输、字节流TCP
SOCK_DGRAM无连接、不可靠、数据报UDP
SOCK_RAW原始网络层访问IP/ICMP
SOCK_SEQPACKET有序分组服务SCTP
3. protocol(协议选择)
取值说明
0自动选择默认协议(推荐)
IPPROTO_TCP显式指定TCP协议(=6)
IPPROTO_UDP显式指定UDP协议(=17)
IPPROTO_RAW原始IP协议(需要权限)

标准协议组合

// TCP套接字
socket(AF_INET, SOCK_STREAM, 0);

// UDP套接字
socket(AF_INET, SOCK_DGRAM, 0);

// 原始ICMP套接字
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

(四)返回值处理

返回值说明
正整数新创建的套接字描述符(>=3,0-2为stdin/stdout/stderr)
-1创建失败,检查errno:<br>• EACCES(权限不足)<br>• EMFILE(描述符耗尽)<br>• EPROTONOSUPPORT(协议不支持)

(五)使用示例

1. 创建TCP套接字
int tcp_sock = socket(AF_INET, SOCK_STREAM, 0);
if (tcp_sock == -1) {
    perror("TCP socket creation failed");
    exit(EXIT_FAILURE);
}
2. 创建UDP套接字
int udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_sock == -1) {
    perror("UDP socket creation failed");
    exit(EXIT_FAILURE);
}
3. 创建原始套接字(需root权限)
int raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (raw_sock == -1) {
    perror("Raw socket creation failed");
    exit(EXIT_FAILURE);
}

五、connect() 函数详解

(一)函数原型

#include <sys/types.h>
#include <sys/socket.h>

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

(二)核心功能

  • 建立连接:在客户端与目标服务器之间建立通信链路(TCP三次握手)
  • 地址绑定:对于UDP可预先指定默认接收地址
  • 错误检测:验证网络可达性与服务可用性

(三)参数解析

参数类型说明
sockfdintsocket()创建的套接字描述符
addrstruct sockaddr*目标服务器地址结构(需转换为实际协议地址结构)
addrlensocklen_t地址结构体的实际长度(字节数)

(四)地址结构示例(IPv4)

struct sockaddr_in {
    sa_family_t    sin_family;  // 地址族(AF_INET)
    in_port_t      sin_port;    // 端口号(网络字节序)
    struct in_addr sin_addr;   // IP地址(网络字节序)
    unsigned char  sin_zero[8]; // 填充字段(全0)
};

struct in_addr {
    in_addr_t s_addr;          // 32位IPv4地址
};

(五)使用流程

sequenceDiagram
    Client->>Socket: 1. socket()
    Client->>Socket: 2. connect()
    Note right of Socket: 触发三次握手
    Socket-->>Client: 连接成功(返回0)
    or Socket-->>Client: 连接失败(返回-1)

(六)返回值处理

返回值说明
0连接建立成功
-1连接失败,检查errno:<br>• ECONNREFUSED(目标拒绝)<br>• ETIMEDOUT(超时)<br>• ENETUNREACH(网络不可达)

(七)典型应用场景

1. TCP客户端连接
int main() {
    // 创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 配置服务器地址
    struct sockaddr_in serv_addr = {
        .sin_family = AF_INET,
        .sin_port = htons(8080),
        .sin_addr.s_addr = inet_addr("192.168.1.100")
    };

    // 建立连接
    if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
        perror("Connection failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 数据传输...
    close(sockfd);
    return 0;
}
2. UDP预连接(非必须)
// UDP套接字创建
int udp_sock = socket(AF_INET, SOCK_DGRAM, 0);

// 指定默认接收地址
struct sockaddr_in serv_addr = {...};
connect(udp_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

// 后续可直接使用send()代替sendto()
send(udp_sock, buffer, strlen(buffer), 0);

六、网络字节序转换与IP地址处理

(一)字节序转换函数

1. 核心函数列表
函数原型功能描述常用场景
uint32_t htonl(uint32_t hostlong)主机到网络序(32位)IP地址转换
uint16_t htons(uint16_t hostshort)主机到网络序(16位)端口号转换
uint32_t ntohl(uint32_t netlong)网络到主机序(32位)接收IP地址解析
uint16_t ntohs(uint16_t netshort)网络到主机序(16位)接收端口号解析
2. 使用示例
// 转换端口号
uint16_t port = 8080;
uint16_t net_port = htons(port);

// 转换IPv4地址
uint32_t ip = 0xC0A80001;  // 192.168.0.1
uint32_t net_ip = htonl(ip);

(二)IP地址转换函数

1. 传统方法(IPv4)
#include <arpa/inet.h>

// 字符串转网络字节序(已过时但常见)
in_addr_t inet_addr(const char *cp);

特性

  • 支持点分十进制格式(如"192.168.0.1")
  • 失败返回INADDR_NONE(通常是0xFFFFFFFF)
  • 不支持IPv6地址

示例

struct sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr("192.168.1.100");
if (addr.sin_addr.s_addr == INADDR_NONE) {
    perror("Invalid IP address");
}
2. 现代方法(推荐)
// 通用地址转换(支持IPv4/IPv6)
int inet_pton(int af, const char *src, void *dst);
参数说明
af地址族(AF_INET/AF_INET6)
src点分地址字符串
dst存储转换结果的缓冲区

返回值

  • 1:成功
  • 0:输入格式错误
  • -1:系统错误

示例

struct in_addr ipv4_addr;
if (inet_pton(AF_INET, "10.0.0.1", &ipv4_addr) <= 0) {
    perror("Address conversion failed");
}

(三)地址转换对照表

字符串地址十六进制值(网络序)十进制值(主机序)
127.0.0.10x7F0000012130706433
192.168.1.1000xC0A801643232235876
255.255.255.2550xFFFFFFFF4294967295

(四)错误处理指南

错误现象可能原因解决方案
inet_addr返回INADDR_NONE地址格式错误使用正则表达式验证输入
inet_pton返回0地址与协议族不匹配检查AF_INET/AF_INET6
转换后数值异常字节序转换错误确认使用ntohl/ntohs

七、bind() 函数详解

(一)函数原型

#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

(二)核心功能

  • 地址绑定:将套接字与指定的网络地址/端口绑定
  • 资源分配:声明对特定网络接口的控制权
  • 服务标识:为客户端提供可连接的目标端点

(三)参数解析

参数类型说明
sockfdintsocket()创建的套接字描述符
addrstruct sockaddr*包含绑定地址信息的结构体指针
addrlensocklen_t地址结构体的实际长度(字节数)

(四)使用场景对比

场景服务器端客户端
必要性必须调用(需固定服务端口)通常省略(系统自动分配临时端口)
典型地址明确指定IP和端口(如0.0.0.0:80)可指定为INADDR_ANY+0(自动选择)
错误处理严格检查EADDRINUSE(端口占用)关注EACCES(特权端口权限)

(五)服务器端典型用法

// 创建TCP套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);

// 配置绑定地址
struct sockaddr_in serv_addr = {
    .sin_family = AF_INET,
    .sin_port = htons(8080),             // 明确指定端口
    .sin_addr.s_addr = htonl(INADDR_ANY) // 监听所有接口
};

// 绑定地址
if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
    perror("Bind failed");
    close(sockfd);
    exit(EXIT_FAILURE);
}

(六)客户端特殊用法

// 创建UDP套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

// 指定源端口(特殊需求)
struct sockaddr_in cli_addr = {
    .sin_family = AF_INET,
    .sin_port = htons(54321),            // 固定客户端端口
    .sin_addr.s_addr = inet_addr("192.168.1.100")
};

if (bind(sockfd, (struct sockaddr*)&cli_addr, sizeof(cli_addr)) == -1) {
    perror("Client bind failed");
    close(sockfd);
    exit(EXIT_FAILURE);
}

(七)错误处理指南

错误码原因描述解决方案
EADDRINUSE地址/端口已被占用更换端口或等待释放
EACCES无权限绑定特权端口(<1024)使用sudo运行或改用非特权端口
EINVAL套接字已绑定过地址检查是否重复调用bind()
ENOTSOCK文件描述符不是套接字验证sockfd来源

八、listen() 函数详解

(一)函数原型

#include <sys/socket.h>

int listen(int sockfd, int backlog);

(二)核心功能

  • 监听模式:将套接字设置为被动接收连接状态
  • 队列管理:建立连接请求缓冲队列
  • 服务准备:为后续accept()调用提供就绪环境

(三)参数解析

参数类型说明
sockfdint已绑定的流式套接字描述符(需先调用bind()
backlogint等待连接队列的最大长度(详见下文说明)

(四)队列机制详解

graph LR
    A[Client SYN] --> B{SYN队列<br>(未完成握手)}
    B -->|完成三次握手| C[ACCEPT队列<br>(已建立连接)]
    C --> D[accept()取出]
    
    style B fill:#f9d5e5,stroke:#f25287
    style C fill:#d5e8d4,stroke:#82b366
  • SYN队列(半连接队列):存储未完成三次握手的请求
  • ACCEPT队列(全连接队列):存储已完成握手的连接
  • backlog参数:通常指ACCEPT队列的最大长度(不同系统实现有差异)

(五)使用规范

1. 前置条件
// 创建套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);

// 绑定地址(必须步骤)
struct sockaddr_in addr = {...};
bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));

// 开始监听
listen(sockfd, SOMAXCONN);  // SOMAXCONN为系统允许的最大值
2. 推荐配置
操作系统最大backlog值说明
Linux/proc/sys/net/core/somaxconn默认值通常为4096
FreeBSDkern.ipc.soacceptqueue默认值通常为128
通用方案使用SOMAXCONN宏定义自动适配系统最大值

(六)错误处理

错误码原因描述解决方案
EADDRINUSE地址/端口已被占用检查端口冲突,使用netstat -tulnp排查
EBADF无效套接字描述符验证sockfd是否已正确创建
EINVAL套接字未绑定或类型错误确保先调用bind()且为流式套接字
ENOTSOCK文件描述符不是套接字检查sockfd来源

九、accept() 函数详解

(一)函数原型

#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

(二)核心功能

  • 连接接入:从已完成连接队列中取出首个连接
  • 创建新套接字:生成专用于该连接的通信套接字
  • 客户端信息获取(可选):记录客户端地址信息

(三)参数解析

参数类型说明
sockfdint处于监听状态的流式套接字描述符
addrstruct sockaddr*客户端地址信息存储缓冲区(可NULL)
addrlensocklen_t*输入:缓冲区大小<br>输出:实际地址长度(值-结果参数)

(四)使用流程

sequenceDiagram
    Client->>Server: SYN
    Server->>Client: SYN-ACK
    Client->>Server: ACK
    Note right of Server: 连接进入ACCEPT队列
    Server->>Server: accept()
    Server-->>Client: 建立数据通道

(五)典型用法

1. 基础用法(不获取客户端信息)
int new_sock = accept(listen_sock, NULL, NULL);
if (new_sock == -1) {
    perror("Accept failed");
    // 错误处理
}
2. 获取客户端信息
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);

int new_sock = accept(listen_sock, 
                     (struct sockaddr*)&client_addr,
                     &addr_len);

if (new_sock != -1) {
    printf("Client from %s:%d\n",
           inet_ntoa(client_addr.sin_addr),
           ntohs(client_addr.sin_port));
}

(六)返回值说明

返回值说明
正整数新通信套接字描述符(>=3)
-1失败,检查errno:<br>• EAGAIN/EWOULDBLOCK(非阻塞模式无连接)<br>• ECONNABORTED(连接中止)<br>• EINTR(被信号中断)

综合应用:

 client //作为主动的角色 

#include<stdio.h>
#include <sys/types.h>	       /* See NOTES */
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>


//./client port ip

int main(int argc, const char *argv[])
{
	if(argc != 3)
	{
		printf("Usage: %s <port> <ip>\n",argv[0]);
		return -1;
	}
	int fd = socket(AF_INET,SOCK_STREAM,0);

	if(fd < 0)
	{
		perror("socket fail\n");
		return -1;
	}

	struct sockaddr_in seraddr;
	bzero(&seraddr,sizeof(seraddr));

	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(atoi(argv[1]));
	seraddr.sin_addr.s_addr = inet_addr(argv[2]);

	if(connect(fd,(struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
	{
		perror("connect fail");
		return -1;
	}

	printf("connect success!\n");
	
	char buf[1024];
	while(1)
	{
		printf(">");
		fgets(buf,sizeof(buf),stdin);
		write(fd,buf,strlen(buf)+1);
		
		if(strncmp(buf,"quit",4) == 0)
		{
			break;
		}

		read(fd,buf,sizeof(buf));
		printf("s: %s",buf);
		
	}

	close(fd);
	return 0;
}

server //被动角色 

#include<stdio.h>
#include <sys/types.h>	       /* See NOTES */
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[])
{
	if(argc != 3)
	{
		printf("Usage: %s <port> <ip>\n",argv[0]);
		return -1;
	}

	//1.socket 创建通信一端
	int fd = socket(AF_INET,SOCK_STREAM,0);

	if(fd < 0)
	{
		perror("socket fail\n");
		return -1;
	}

	struct sockaddr_in seraddr;
	bzero(&seraddr,sizeof(seraddr));

	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(atoi(argv[1]));
	seraddr.sin_addr.s_addr = inet_addr(argv[2]);

	//2.bind--绑定服务端的地址信息
	if(bind(fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
	{
		perror("bind fail");
		return -1;
	}

	//3.listen 监听
	if(listen(fd,5) < 0)
	{
		perror("listen fail");
		return -1;
	}

	//4.accept
	int connfd = accept(fd,NULL,NULL);

	if(connfd < 0)
	{
		perror("accept fail");
		return -1;
	}
	printf("-----client----connectted\n");

	char buf[1024];
	char sbuf[1024];
	while(1)
	{
		read(connfd,buf,sizeof(buf));

		printf("c: %s\n",buf);

		if(strncmp(buf,"quit",4) == 0)
		{
			break;
		}
		sprintf(sbuf,"server + %s\n",buf);
		write(connfd,sbuf,strlen(sbuf)+1);
	}

	close(fd);
	close(connfd);
	return 0;
}

标签:网络通信,addr,AF,int,----,地址,Linux,接字,include
From: https://blog.csdn.net/2401_84382970/article/details/145946397

相关文章