在新建立的文件系统使用DNS及搭建ftp客服端

本文介绍如何在BusyBox环境中配置DNS并实现域名解析,同时详细说明了搭建FTP客户端的过程,包括所需文件和服务配置。

接用busybox-1.1.0打造自己的2410文件系统

使用DNS

1.创建DNS域名解释配置文件

[root@localhost etc]# vi resolv.conf (指定 DNS 服务器)

 

meserver 192.168.2.1

nameserver 202.96.134.133

2busybox中要使用DNS时,要保证/etc/resolv.conf, [/etc/nsswitch.conf,/etc/hosts,/etc/host.conf,/etc/hostname]文件存在(其中[  ]内的内容是否需要没有经过验证,反正有了肯定不会错,我做文件系统就没用它们,呵呵);同时要求libnss_dns,libnss_files,libresolv库存在。

3.验证:

ping www.google.cn

搭建ftp客服端

1.copy ftp命令到usr/bin目录下(ftp命令在dma2410开发板文件系统中copy过来)

2.etc/目录下创建services文件(记录知名网络服务及端口,ftp及网络编程依赖于此文件

),内容如下

[root@localhost root]# vi etc/services  

# service-name  port/protocol  [aliases ...]   [# comment]

 

tcpmux          1/tcp

echo            7/tcp

echo            7/udp

systat          11/tcp          users

daytime         13/tcp

daytime         13/udp

netstat         15/tcp

ftp-data        20/tcp

ftp             21/tcp

ssh             22/tcp

ssh             22/udp

telnet          23/tcp

smtp            25/tcp          mail

time            37/tcp          timserver

time            37/udp          timserver

nameserver      42/tcp          name

whois           43/tcp          nicname

bootps          67/tcp

bootps          67/udp

bootpc          68/tcp

bootpc          68/udp

tftp            69/udp

finger          79/tcp

www             80/tcp          http

www             80/udp

pop3            110/tcp         pop-3

pop3            110/udp         pop-3

sunrpc          111/tcp         portmapper

sunrpc          111/udp         portmapper

auth            113/tcp         authentication tap ident

nntp            119/tcp         readnews untp

ntp             123/tcp

ntp             123/udp

snmp            161/udp

snmp-trap       162/udp         snmptrap

 


# 再谈 Linux Socket 编程技术 @[TOC] --- #### 1. 简介 ##### Socket 编程的基本概念 Socket 编程是指利用操作系统提供的套接字(Socket)接口,实现网络通信的编程方法。Socket 可以看作是两个网络应用程序之间进行双向通信的端点,类似于现实生活中的电话插座。它封装了底层网络协议的复杂性,为开发者提供了简单易用的接口,使得不同主机上的进程能够通过网络交换数据。 在 Socket 编程中,通信的两端通常分为客户端(Client)和服务器端(Server)。客户端主动发起连接请求,而服务器端被动监听并接受连接。Socket 支持多种协议,包括可靠的面向连接的 TCP(传输控制协议)和不可靠的无连接 UDP(用户数据报协议)。 ##### 网络通信模型(TCP/IP、UDP) 1. **TCP/IP 通信模型** - **TCP(Transmission Control Protocol)**:是一种面向连接的、可靠的传输协议。它通过三次握手建立连接,确保数据按序传输,并提供错误检测和重传机制。适用于需要高可靠性的应用,如网页浏览(HTTP)、文件传输(FTP)、电子邮件(SMTP)等。 - **IP(Internet Protocol)**:负责数据包的路由和寻址,确保数据能够从源主机传输到目标主机。 2. **UDP 通信模型** - **UDP(User Datagram Protocol)**:是一种无连接的、不可靠的传输协议。它不保证数据包的顺序或可靠性,但传输效率高,延迟低。适用于实时性要求高的应用,如视频流(RTP)、在线游戏、DNS 查询等。 ##### Socket 在 Linux 中的角色 在 Linux 系统中,Socket 是内核提供的一种文件描述符(File Descriptor),开发者可以通过标准的文件 I/O 操作(如 `read`、`write`)来读写 Socket。Linux 提供了丰富的系统调用(System Calls)支持 Socket 编程,例如: - `socket()`:创建一个的 Socket。 - `bind()`:将 Socket 绑定到一个特定的 IP 地址和端口。 - `listen()`:使服务器端 Socket 进入监听状态。 - `accept()`:接受客户端的连接请求。 - `connect()`:客户端发起连接请求。 - `send()`/`recv()`:发送和接收数据。 Linux 的 Socket 接口遵循 POSIX 标准,具有良好的跨平台兼容性,使得基于 Socket 开发的网络程序能够在不同 UNIX/Linux 系统上运行。此外,Linux 内核还支持多种 Socket 类型,如流式 Socket(SOCK_STREAM,对应 TCP)和数据报 Socket(SOCK_DGRAM,对应 UDP),以及原始 Socket(SOCK_RAW)用于直接访问底层协议。 Socket 编程是 Linux 网络应用程序开发的基础,广泛应用于 Web 服务器、数据库、即时通讯、分布式系统等领域。 --- #### 2. Socket 类型协议 1. **流式 Socket (SOCK_STREAM,TCP)** - 提供面向连接的、可靠的字节流传输服务 - 保证数据按顺序到达且无重复 - 典型应用场景: * Web 浏览 (HTTP/HTTPS) * 文件传输 (FTP) * 电子邮件 (SMTP/POP3) - 建立连接需要三次握手,断开需要四次挥手 - TCP 头部包含序列号、确认号等控制字段 2. **数据报 Socket (SOCK_DGRAM,UDP)** - 提供无连接的、不可靠的数据报传输服务 - 不保证数据顺序和可靠性,但传输效率高 - 典型应用场景: * 实时音视频传输 * DNS 查询 * 在线游戏 - 每个数据包独立路由,头部仅包含源/目标端口和长度 3. **原始 Socket (SOCK_RAW)** - 允许直接访问底层协议(如IP/ICMP) - 可以自定义协议头部字段 - 典型用途: * 网络嗅探工具开发 * 自定义协议实现 * 网络安全测试 - 需要管理员权限才能创建 - 可以接收所有经过网卡的数据包(包括异常包) > 注:选择 Socket 类型时应根据应用场景的需求权衡可靠性(TCP)实时性(UDP) --- #### 3. 基本 Socket 函数 以下是网络编程中常用的基本 Socket 函数及其详细说明: 1. **`socket()`**:创建 Socket - 功能:创建一个的 Socket 描述符,指定通信域(如 IPv4/IPv6)、Socket 类型(如流式 TCP 或数据报 UDP)和协议(通常为 0,表示自动选择)。 - 示例: ```c int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建 TCP Socket ``` 2. **`bind()`**:绑定 IP 和端口 - 功能:将 Socket 绑定到特定的 IP 地址和端口号,通常用于服务器端。 - 示例: ```c struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; // 绑定所有可用 IP serv_addr.sin_port = htons(8080); // 绑定端口 8080 bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); ``` 3. **`listen()`**:监听连接(TCP) - 功能:将 Socket 设置为被动监听模式,等待客户端连接请求,仅适用于 TCP。 - 参数:`backlog` 指定等待连接队列的最大长度。 - 示例: ```c listen(sockfd, 5); // 允许最多 5 个未处理的连接请求 ``` 4. **`accept()`**:接受连接(TCP) - 功能:从监听队列中接受一个客户端连接请求,返回一个的 Socket 描述符用于通信。 - 示例: ```c struct sockaddr_in cli_addr; socklen_t clilen = sizeof(cli_addr); int newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen); ``` 5. **`connect()`**:发起连接(TCP/UDP) - 功能:客户端调用此函数向服务器发起连接(TCP)或直接发送数据(UDP)。 - 示例(TCP): ```c struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(8080); inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); ``` 6. **`send()`/`recv()`**:数据收发(TCP) - 功能:在已建立的 TCP 连接上发送或接收数据。 - 示例: ```c char buffer[1024]; recv(newsockfd, buffer, sizeof(buffer), 0); // 接收数据 send(newsockfd, "Hello, client!", 14, 0); // 发送数据 ``` 7. **`sendto()`/`recvfrom()`**:数据收发(UDP) - 功能:用于无连接的 UDP 通信,指定目标地址或获取来源地址。 - 示例: ```c struct sockaddr_in cli_addr; char buffer[1024]; socklen_t len = sizeof(cli_addr); recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&cli_addr, &len); sendto(sockfd, "Reply", 6, 0, (struct sockaddr*)&cli_addr, len); ``` 8. **`close()`**:关闭 Socket - 功能:释放 Socket 资源,终止通信。 - 示例: ```c close(sockfd); // 关闭 Socket ``` 这些函数是网络编程的基础,适用于构建客户端-服务器模型或点对点通信。 --- #### 4. TCP Socket 编程示例 以下是一个完整的TCP服务器端实现示例,展示了基本的Socket编程流程,包括创建Socket、绑定端口、监听连接、收发数据等关键步骤: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define PORT 8080 // 定义服务器监听端口 #define BUFFER_SIZE 1024 // 定义缓冲区大小 int main() { int server_fd, new_socket; struct sockaddr_in address; int addrlen = sizeof(address); char buffer[BUFFER_SIZE] = {0}; // 初始化接收缓冲区 char *response = "Hello from server"; // 定义服务器响应消息 // 1. 创建Socket文件描述符 // AF_INET表示IPv4协议,SOCK_STREAM表示TCP协议 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 2. 配置服务器地址结构 address.sin_family = AF_INET; // 使用IPv4地址族 address.sin_addr.s_addr = INADDR_ANY; // 监听任意网卡地址 address.sin_port = htons(PORT); // 设置端口号(转换为网络字节序) // 3. 绑定Socket到指定IP和端口 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 4. 开始监听连接请求 // 第二个参数3表示等待连接队列的最大长度 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } printf("Server listening on port %d...\n", PORT); // 5. 接受客户端连接,创建的Socket用于通信 if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } // 6. 读取客户端发送的数据 int valread = read(new_socket, buffer, BUFFER_SIZE); printf("Received from client: %s\n", buffer); // 7. 向客户端发送响应数据 send(new_socket, response, strlen(response), 0); printf("Response sent to client\n"); // 8. 关闭Socket连接 close(new_socket); close(server_fd); return 0; } ``` **应用场景说明**: 1. 这个示例可作为简单的TCP服务器基础框架 2. 可用于开发网络聊天程序的基础通信模块 3. 适用于需要实现基本请求-响应模型的网络服务 4. 可作为学习网络编程的入门示例 **扩展建议**: 1. 可以添加多线程处理以支持多个客户端连接 2. 可以增加错误处理的健壮性 3. 可以扩展为支持HTTP协议的简单Web服务器 4. 可以添加日志记录功能 **注意事项**: 1. 需要root权限才能绑定1024以下的端口 2. 实际应用中应考虑设置SO_REUSEADDR选项 3. 网络字节序转换(htons)是必须的 4. 生产环境需要更完善的错误处理机制 --- #### 5. UDP Socket 编程示例 UDP (User Datagram Protocol) 是一种无连接的传输协议,适用于对实时性要求高但允许少量丢包的应用场景,如视频会议、在线游戏等。下面是一个完整的UDP服务器实现示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define BUFFER_SIZE 1024 #define SERVER_PORT 8080 int main() { int sockfd; struct sockaddr_in server_addr, client_addr; char buffer[BUFFER_SIZE]; char *response_message = "Hello from UDP server"; // 1. 创建Socket // AF_INET表示IPv4协议族 // SOCK_DGRAM指定使用数据报套接字(UDP) // 0表示使用默认协议 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } // 2. 配置服务器地址结构 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; // IPv4 server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡 server_addr.sin_port = htons(SERVER_PORT); // 设置端口号,htons确保网络字节序 // 3. 绑定Socket到指定端口 if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("Bind failed"); close(sockfd); exit(EXIT_FAILURE); } printf("UDP server is running on port %d...\n", SERVER_PORT); // 4. 接收客户端数据 socklen_t client_addr_len = sizeof(client_addr); ssize_t recv_len = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client_addr, &client_addr_len); if (recv_len < 0) { perror("Receive failed"); } else { buffer[recv_len] = '\0'; // 确保字符串以null结尾 printf("Received %zd bytes from %s:%d\n", recv_len, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); printf("Message: %s\n", buffer); } // 5. 发送响应数据 if (sendto(sockfd, response_message, strlen(response_message), 0, (struct sockaddr *)&client_addr, client_addr_len) < 0) { perror("Send failed"); } // 6. 关闭Socket close(sockfd); return 0; } ``` 应用场景说明: 1. 实时音视频传输:UDP的低延迟特性使其适合视频会议应用 2. DNS查询:DNS协议通常使用UDP进行域名解析 3. 在线游戏:多数网络游戏使用UDP传输玩家位置等实时数据 使用注意事项: 1. UDP不保证数据包的顺序和可靠性 2. 单个UDP数据包最大长度通常为65507字节(IPv4) 3. 需要应用层自己实现超时重传等可靠性机制 4. 可以使用setsockopt()设置接收缓冲区大小 该示例展示了UDP服务器端的基本工作流程:创建socket->绑定地址->接收数据->发送响应->关闭socket。客户端实现类似,只是不需要bind操作。 --- #### 6. 高级 Socket 编程技术 ##### 多路复用(`select()`、`poll()`、`epoll()`) 多路复用技术允许单个线程同时监控多个 Socket 文件描述符,提高网络程序的并发性能。 - **`select()`**:通过轮询方式检查多个文件描述符的状态,支持跨平台但有 1024 个描述符的限制。 ```c fd_set read_fds; FD_ZERO(&read_fds); FD_SET(sockfd, &read_fds); select(sockfd + 1, &read_fds, NULL, NULL, &timeout); ``` - **`poll()`**:改进 `select()` 的限制,使用链表结构存储文件描述符,但效率仍依赖轮询。 ```c struct pollfd fds[1]; fds[0].fd = sockfd; fds[0].events = POLLIN; poll(fds, 1, timeout_ms); ``` - **`epoll()`**(Linux 特有):基于事件驱动的回调机制,适用于高并发场景。 ```c int epfd = epoll_create1(0); struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = sockfd; epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev); epoll_wait(epfd, events, MAX_EVENTS, timeout); ``` ##### 非阻塞 Socket(`fcntl()`) 通过设置 Socket 为非阻塞模式,可以避免 `accept()`、`recv()` 等操作阻塞线程。 ```c int flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); ``` - **应用场景**:适用于需要异步处理连接或数据的程序,如游戏服务器、实时通信系统。 ##### Socket 超时设置 可通过 `setsockopt()` 设置 Socket 操作的超时时间,防止长时间阻塞。 ```c struct timeval timeout; timeout.tv_sec = 5; // 5秒超时 timeout.tv_usec = 0; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); ``` ##### 综合实例(高并发 Echo 服务器) 以下是一个结合 `epoll()` 和非阻塞 Socket 实现的 Echo 服务器框架: ```c // 初始化 epoll int epfd = epoll_create1(0); struct epoll_event ev, events[MAX_EVENTS]; // 设置监听 Socket 为非阻塞 fcntl(listen_fd, F_SETFL, O_NONBLOCK); ev.events = EPOLLIN | EPOLLET; // 边缘触发模式 ev.data.fd = listen_fd; epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev); while (1) { int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1); for (int i = 0; i < nfds; i++) { if (events[i].data.fd == listen_fd) { // 处理连接 int conn_fd = accept(listen_fd, ...); fcntl(conn_fd, F_SETFL, O_NONBLOCK); ev.events = EPOLLIN | EPOLLET; ev.data.fd = conn_fd; epoll_ctl(epfd, EPOLL_CTL_ADD, conn_fd, &ev); } else { // 处理客户端数据 char buffer[1024]; ssize_t n = recv(events[i].data.fd, buffer, sizeof(buffer), 0); if (n > 0) { send(events[i].data.fd, buffer, n, 0); } else { close(events[i].data.fd); } } } } ``` - **适用场景**:适用于需要高并发、低延迟的网络服务,如即时聊天、在线游戏服务器等。 --- #### 8. 实际应用案例 ##### 简单的 HTTP Server 使用 Node.js 内置的 `http` 模块可以快速搭建一个基础的 HTTP 服务器。以下是一个完整的示例代码: ```javascript const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello, Node.js HTTP Server!\n'); }); server.listen(3000, () => { console.log('Server running at http://localhost:3000/'); }); ``` **功能说明:** 1. `http.createServer` 创建一个服务器实例,接收请求并返回响应。 2. `res.writeHead` 设置 HTTP 响应状态码和头部信息。 3. `res.end` 发送响应内容并结束请求。 4. `server.listen` 启动服务器,监听 3000 端口。 **应用场景:** - 快速测试 API 接口 - 本地开发环境模拟后端服务 - 学习 HTTP 协议和请求/响应机制 ##### 实时聊天程序 使用 Node.js 结合 `socket.io` 库可以轻松实现一个实时聊天应用。以下是关键实现步骤: 1. **安装依赖** ```bash npm install socket.io express ``` 2. **服务端代码** ```javascript const express = require('express'); const socketIO = require('socket.io'); const app = express(); const server = app.listen(3000, () => { console.log('Chat server running on port 3000'); }); const io = socketIO(server); io.on('connection', (socket) => { console.log('New user connected'); socket.on('chat message', (msg) => { io.emit('chat message', msg); // 广播消息给所有客户端 }); socket.on('disconnect', () => { console.log('User disconnected'); }); }); ``` 3. **客户端代码(HTML + JavaScript)** ```html <script src="/socket.io/socket.io.js"></script> <script> const socket = io(); socket.on('chat message', (msg) => { // 接收并显示消息 const messages = document.getElementById('messages'); messages.innerHTML += `<li>${msg}</li>`; }); // 发送消息 document.getElementById('send').addEventListener('click', () => { const message = document.getElementById('message').value; socket.emit('chat message', message); }); </script> ``` **核心功能:** - 基于 WebSocket 实现双向实时通信 - `socket.emit` 发送消息,`socket.on` 监听事件 - 自动处理连接/断开事件 **应用场景:** - 在线客服系统 - 多人在线游戏聊天 - 协同办公工具的实时通知 --- #### 9. 总结 ##### Socket 编程的核心要点 1. **基本概念** - **Socket 本质**:Socket 是网络通信的端点,用于实现不同主机或同一主机上不同进程间的数据传输。 - **通信模型**:常见的通信模型包括 TCP(面向连接、可靠传输)和 UDP(无连接、不可靠但高效)。 - **IP 地址端口**:Socket 通信依赖 IP 地址标识主机,端口号标识具体服务(如 HTTP 默认端口 80)。 2. **核心步骤(以 TCP 为例)** - **服务端流程**: 1. 创建 Socket(`socket()`)。 2. 绑定 IP 和端口(`bind()`)。 3. 监听连接请求(`listen()`)。 4. 接受客户端连接(`accept()`)。 5. 收发数据(`send()`/`recv()`)。 6. 关闭连接(`close()`)。 - **客户端流程**: 1. 创建 Socket。 2. 连接服务端(`connect()`)。 3. 收发数据。 4. 关闭连接。 3. **关键问题优化** - **粘包处理**:TCP 是字节流协议,需自定义协议(如固定长度头或分隔符)解决粘包问题。 - **并发模型**:多线程/多进程(如 `fork()`)、IO 多路复用(如 `select()`/`epoll`)可提升服务端并发能力。 - **错误处理**:需捕获 `ECONNRESET`(连接重置)等异常,确保程序健壮性。 ##### 进一步学习资源推荐 1. **书籍** - 《UNIX 网络编程》(W. Richard Stevens):经典教材,涵盖 Socket 编程深度实践。 - 《TCP/IP 详解 卷1:协议》(W. Richard Stevens):深入理解底层协议栈。 2. **在线资源** - [Beej's Guide to Network Programming](https://beej.us/guide/bgnet/):免费、易懂的 Socket 编程教程(中英文版均有)。 - Linux `man` 手册:命令行输入 `man socket` 查看系统调用文档。 3. **实践方向** - 实现简易聊天程序(TCP/UDP 双版本)。 - 结合 HTTP 协议实现微型 Web 服务器(如解析 GET 请求返回文件)。 - 学习开源项目(如 Nginx、Redis)的网络模块设计。 (注:示例代码工具推荐可根据读者基础选择性补充。) --- **研究学习不易,点赞易。 工作生活不易,收藏易,点收藏不迷茫 :)** ---
05-25
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值