Linux网络编程教程

第一章:Linux网络编程基础
1 Linux网络编程
Linux网络编程是指利用Linux操作系统提供的网络API进行网络应用程序的开发,Linux网络编程具有广泛的应用场景,如Web服务器、文件传输、网络通信等。
2 Linux网络编程环境搭建
在进行Linux网络编程之前,需要搭建一个适合开发的环境,以下是一个基本的Linux网络编程环境搭建步骤:
| 步骤 | 说明 |
|---|---|
| 1 | 安装Linux操作系统 |
| 2 | 安装编译器,如gcc |
| 3 | 安装网络编程库,如libevent、libev等 |
| 4 | 安装开发工具,如Visual Studio Code、Eclipse等 |
3 Linux网络编程常用API
Linux网络编程中常用的API有socket、inet、arpa等,以下是一些常用的API及其功能:
| API | 功能 |
|---|---|
| socket() | 创建套接字 |
| bind() | 绑定套接字地址 |
| listen() | 监听套接字 |
| accept() | 接受连接请求 |
| connect() | 连接服务器 |
| send() | 发送数据 |
| recv() | 接收数据 |
| close() | 关闭套接字 |
第二章:Linux网络编程实例

1 简单的TCP客户端/服务器程序
以下是一个简单的TCP客户端/服务器程序实例:
// 服务器端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello from server";
// 创建socket文件描述符
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 强制绑定到端口8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
// 绑定socket到端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听端口
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 接受连接请求
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 发送数据到客户端
send(new_socket, hello, strlen(hello), 0);
printf("Hello message sent\n");
// 接收客户端数据
read(new_socket, buffer, 1024);
printf("Message from client: %s\n", buffer);
// 关闭套接字
close(new_socket);
close(server_fd);
return 0;
}
// 客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
int main() {
struct sockaddr_in serv_addr;
int sock = 0;
char buffer[1024] = {0};
char *hello = "Hello from client";
// 创建socket文件描述符
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8080);
// 将IP地址解析为二进制形式
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {
printf("\nInvalid address/ Address not supported \n");
return -1;
}
// 连接到服务器
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
printf("\nConnection Failed \n");
return -1;
}
// 发送数据到服务器
send(sock, hello, strlen(hello), 0);
printf("Hello message sent\n");
// 接收服务器数据
read(sock, buffer, 1024);
printf("Message from server: %s\n", buffer);
// 关闭套接字
close(sock);
return 0;
}
2 经验案例:使用libevent库实现多线程网络服务器
在处理大量并发连接时,使用libevent库可以简化网络服务器的开发,以下是一个使用libevent库实现的多线程网络服务器案例:
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/dns.h>
#include <event2/log.h>
#include <event2/util.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
void event_callback(struct evutil_socket_t fd, short event, void *arg) {
struct evbuffer *buf = (struct evbuffer *)arg;
char buffer[1024] = {0};
ssize_t nread;
// 读取数据
nread = evbuffer_read(buf, buffer, sizeof(buffer) - 1);
if (nread > 0) {
buffer[nread] = '\0';
printf("Received: %s\n", buffer);
// 发送响应
evbuffer_add_printf(buf, "HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nHello World!");
evbuffer_write(buf, fd);
}
}
int main() {
struct event_base *base;
struct evdns_base *dns_base;
struct evutil_socket_t fd;
struct sockaddr_in serv;
struct event *ev;
struct evbuffer *buf;
// 初始化libevent
base = event_base_new();
dns_base = evdns_base_new(base, 0, NULL);
// 创建socket
fd = evutil_socket_new(AF_INET, SOCK_STREAM, 0);
evutil_make_socket_nonblocking(fd);
memset(&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(8080);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
// 绑定socket到端口
if (evutil_bind(fd, (struct sockaddr *)&serv, sizeof(serv)) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
// 监听端口
if (evutil_listen(fd, 10) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 创建事件
ev = ev_socket_new(base);
ev_socket_setfd(ev, fd);
ev_socket_set_events(ev, EV_READ);
ev_socket_set_callback(ev, event_callback, NULL);
// 启动事件循环
event_base_dispatch(base);
// 清理资源
evutil_socket_close(fd);
ev_socket_free(ev);
evdns_base_free(dns_base, 1);
event_base_free(base);
return 0;
}
第三章:Linux网络编程FAQs

FAQ 1:Linux网络编程中,如何实现TCP客户端和服务器之间的数据传输?
解答:在Linux网络编程中,可以使用socket API实现TCP客户端和服务器之间的数据传输,客户端使用connect()函数连接到服务器,然后使用send()和recv()函数发送和接收数据。
FAQ 2:如何使用libevent库实现多线程网络服务器?
解答:使用libevent库实现多线程网络服务器,需要使用evsocket_new()创建socket,然后使用evsocket_setfd()设置socket文件描述符,最后使用evsocket_set_events()设置socket事件,并注册回调函数,在回调函数中,可以处理客户端连接和数据传输。
第四章:参考文献
《Linux网络编程》
《Linux网络编程实战》
《TCP/IP详解》
《UNIX网络编程》
《libevent网络编程》















