实现TFTP时候遇到的坑

TFTP是一个非常简单的用于传输文件的协议。ietf.org/rfc/rfc1350.txt

recvfrom和recv函数

实现下载时一开始我用的是recv函数来获取从服务器发来的数据,但是发现一旦第一个数据包来了之后,给服务器返回一个ACK包后,立马服务器就返回一个错误包:

1
2
3
ERROR:
[ERROR_CODE]:4
[ERROR_MSG]:Illegal TFTP operation

这个错误搞了我很久,差点心态搞崩,目前暂时不清楚原因。

参考

  1. 项目概览 - tftpx - GitCode
  2. W.Richard.Stevens 的 TCP/IP Illustrated Volume 1: The Protocols(TCP/IP详解 卷1:协议).

实现在线聊天平台遇到的坑

makefile问题

我有个用C语言实现在线聊天的工程,这个工程有服务器端和客户端,我放在工程目录下的server和client中,还有个放头文件的inc目录,src目录下还有两个代码公共的.c文件
目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
project_root/
|-- inc/
| |-- loger.h
| |-- linklist.h
|-- src/
| |-- loger.c
| |-- linklist.c
|-- server
| |-- server.c
|-- client
| |-- client.c
|-- Makefile

我的makefile文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Makefile

# 编译器
CC = gcc

# 编译选项
CFLAGS = -Wall -Werror

# 目标文件夹
BUILD_DIR = build

# 源文件夹
SRC_DIR = src
INC_DIR = inc
SERVER_DIR = server
CLIENT_DIR = client

# 服务器和客户端的可执行文件名
SERVER_EXE = $(BUILD_DIR)/server
CLIENT_EXE = $(BUILD_DIR)/client

# 共享的源文件
COMMON_SRC = $(wildcard $(SRC_DIR)/*.c)

# 服务器和客户端的源文件
SERVER_SRC = $(SERVER_DIR)/server.c
CLIENT_SRC = $(CLIENT_DIR)/client.c

# 服务器和客户端的目标文件
SERVER_OBJ = $(BUILD_DIR)/server.o
CLIENT_OBJ = $(BUILD_DIR)/client.o
COMMON_OBJ = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(COMMON_SRC))

# 创建 build 目录
$(shell mkdir -p $(BUILD_DIR))

# 所有的目标
all: server client

# 服务器目标
server: $(SERVER_EXE)

$(SERVER_EXE): $(SERVER_OBJ) $(COMMON_OBJ)
$(CC) $(CFLAGS) -o $@ $^

$(SERVER_OBJ): $(SERVER_SRC)
$(CC) $(CFLAGS) -I$(INC_DIR) -c $< -o $@

# 客户端目标
client: $(CLIENT_EXE)

$(CLIENT_EXE): $(CLIENT_OBJ) $(COMMON_OBJ)
$(CC) $(CFLAGS) -o $@ $^

$(CLIENT_OBJ): $(CLIENT_SRC)
$(CC) $(CFLAGS) -I$(INC_DIR) -c $< -o $@

# 公共源文件目标
$(COMMON_OBJ): $(COMMON_SRC)
$(CC) $(CFLAGS) -I$(INC_DIR) -c $< -o $@

# 清理目标
clean:
rm -rf $(BUILD_DIR)/*.o $(SERVER_EXE) $(CLIENT_EXE)

# 伪目标,防止与文件名冲突
.PHONY: all server client clean

现在的问题是,我编译的时候显示linklist内部的函数multiple definition,我没有重复定义,也启用了头文件保护,这是为啥?

下面是ChatGPT的解答:

问题出现在多次定义相同函数或变量时,通常在连接阶段,链接器会遇到不同目标文件中相同函数或变量的多次定义。在你的Makefile中,你有一个COMMON_SRC变量,其中包含了src目录中的所有源文件。这个变量然后用于创建COMMON_OBJ变量。但是,当你单独编译每个源文件时,COMMON_OBJ变量并未被使用。相反,每个单独的源文件都被单独编译。

为了解决这个问题,你应该修改COMMON_OBJ的规则,使用模式规则来分别编译每个源文件。以下是修改后的规则:

1
2
3
# 公共源文件目标
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -I$(INC_DIR) -c $< -o $@

用上述规则替换Makefile中现有的$(COMMON_OBJ)规则。这样,src目录中的每个源文件将被单独编译成自己的目标文件,链接器将不会遇到相同函数的多次定义。

在Makefile中找到相应的行,并进行修改。修改后,尝试重新构建项目,多次定义的问题应该会得到解决。