13.1 Linux_网络编程_TCP/UDP

字节序

1、概述

什么是字节序:

字节序就是字节的存储顺序,分为大端字节序和小端字节序。

  • 大端字节序:低地址存高位(网络)
  • 小端字节序:低地址存低位(主机)

检验主机字节序模式:

#include <stdio.h>

int main(){

	unsigned int a = 0x11223344;
	unsigned char b = *((unsigned char *)&a);

	if(b == 0x44){
		printf("小端字节序\n");
	}else{
		printf("大端字节序\n");
	}
	return 0;
}

2、字节序转换

2.1 端口号字节序转换函数

因为主机使用的是小端字节序,网络使用的是大端字节序,因此在数据传输时,需要先将数据转换为大端字节序传给网络,之后再将数据转换为小端字节序传给另一个主机。

/* h:本机 n:网络 l:32位 s:16位 */

//32位数据(4字节)
uint32_t htonl(uint32_t hostlong);//本机->网络
uint32_t ntohl(uint32_t netlong);//网络->本机
//16位数据(2字节)
uint16_t htons(uint16_t hostshort);//本机->网络
uint16_t ntohs(uint16_t netshort);//网络->本机

返回值:将小端字节序转换为大端字节序后的端口号

参数:端口号值 

2.2 IP地址字节序转换函数

该函数主要是实现点分十进制表示的IP地址转换,而不需要一个字节一个字节的去转换。

2.2.1 IPv4
//点分十进制字符串->网络字节序
in_addr_t inet_addr(const char *cp);
int inet_aton(const char *cp, struct in_addr *inp);
//网络字节序->点分十进制字符串
char *inet_ntoa(struct in_addr in);

inet_addr返回值:ip地址

cp:点分十进制字符串,例如传入"192.168.1.1"这个字符串

inp:ip地址

inet_ntoa返回值:点分十进制字符串

in:ip地址

2.2.1 IPv6
int inet_pton(int af, const char *src, void *dst);
const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);

套接字socket

概述

socket多种含义:

  • 应用编程接口API:socket API,简称socket。 
  • 函数名:socket API中有一个名为socket的函数
  • 端点:比如TCP连接是有两个端点,这两个端点是一对一通信的关系。这个端点也叫socket
  • 文件描述符:socket函数的返回值是一个socket描述符,简称socket

socket的作用:

socket处在应用层与内核之间。在应用层中实现的是与应用相关的代码,在内核中实现的是网络通信相关的代码。在OSI结构中,应用层就是OSI的应用层、表示层、会话层,内核就是运输层、网络层、数据链路层、物理层。

什么是三元组:

三元组指的是IP地址、端口号、协议。该数据通过bind函数进行绑定。

  • IP地址:标识计算机,找到与网络中的哪一个计算机进行通信。
  • 端口号:标识进程,找到与计算机中哪一个进程进行通信。
  • 协议:指定数据以什么样的方式进行传递。主要指TCP、UDP

套接字的类型:

  • 流式套接字 (SOCK_STREAM) :提供可靠的、面向连接的通信流;它使用TCP,从而保证数据传输的可靠性和顺序性
  • 数据报套接字 (SOCK_DGRAM) :定义了一种不可靠、面向无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP
  • 原始套接字(SOCK_RAW) :允许直接访问底层协议,如IP或ICMP,它功能强大但使用较为不便,主要用于协议开发。

socket文件的读写含义:

socket在Linux中也是一种文件,对socket文件进行读就是读取网络传输过来的数据,对socket文件进行写就是向网络中传输相应的数据。

相关函数 

socket相关API:

创建套接字、绑定通信结构体、监听套接字、接收套接字、发起连接

通用 

1、创建套接字
int socket(int domain, int type, int protocol);

返回值:成功返回socket文件描述符,失败返回-1

domain:指定bind中传入的地址族结构体的类型,与sa_family_t的取值要一致。

domain值 含义
AF_UNIX UNIX 域套接字地址族,用于在同一台主机上的进程间通信
AF_INET IPv4 地址族,用于 IPv4 通信
AF_INET6 IPv6 地址族,用于 IPv6 通信

type:套接字的类型,就是"概述"中的说的三种类型

type值 使用的协议
<think>根据提供的错误信息,错误发生在try.vt文件的第33行、38行和46行,错误信息是“near "$": syntax error, unexpected '$'”。这通常意味着在代码中使用了`$`开头的系统任务或函数,但可能由于以下原因导致错误: 1. 该仿真工具不支持该系统任务。 2. 语法错误,比如系统任务名拼写错误或使用方式不正确。 3. 在不能使用系统任务的地方使用了(比如在可综合代码中,但.vt文件通常是测试文件,所以应该支持系统任务)。 另外,错误信息还提到“vlog failed”,说明是编译测试文件时失败。 由于没有提供具体的代码内容,我将根据错误信息推测可能的错误原因,并提供解决方案。 常见的以`$`开头的系统任务包括:`$display`, `$monitor`, `$finish`, `$stop`, `$random`, `$time`, `$readmemh`等。 可能的原因及解决方案: 1. **系统任务名拼写错误**:例如将`$display`写成`$disply`,或者`$finish`写成`$finis`等。请检查这些系统任务名是否正确。 2. **在错误的地方使用**:例如,在模块声明外部使用系统任务。系统任务应该在`initial`或`always`块中使用。 3. **在测试平台中使用了不支持的系统任务**:不同的仿真工具支持的系统任务可能不同。请确认使用的仿真工具(这里是ModelSim)是否支持该任务。 4. **语法错误**:例如,在系统任务调用时缺少分号,或者括号不匹配等。 由于错误发生在第33、38、46行,我们需要检查这些行附近的代码。 下面是一个示例,展示如何正确使用系统任务: ```verilog module test_try; reg clk; reg reset_n; wire clk_sensor; wire clk_st; wire flag; // 实例化被测试模块 try uut ( .clk(clk), .reset_n(reset_n), .clk_sensor(clk_sensor), .clk_st(clk_st), .flag(flag) ); // 生成时钟信号 initial begin clk = 0; forever #10 clk = ~clk; // 假设50MHz,周期20ns end // 测试序列 initial begin reset_n = 0; // 复位 #100; reset_n = 1; // 释放复位 #1000; // 例如,使用$display打印信息 $display("Simulation finished at time %d", $time); // 使用$finish结束仿真 $finish; end endmodule ``` 如果错误是由于在模块外部直接使用系统任务,例如: ```verilog // 错误示例:在模块外部使用系统任务 $display("Hello"); // 这行会报错,因为没有包含在任何块中 module test; ... endmodule ``` 应该将系统任务放在`initial`块中。 另外,如果错误行号指向的是测试平台中的`$`系统任务,请检查: - 是否缺少分号(每个系统任务调用后需要分号) - 括号是否匹配 - 字符串是否正确使用双引号 例如,正确的`$display`使用: ```verilog $display("Time = %t", $time); // 正确 $display(Time = %t, $time); // 错误,缺少双引号 ``` 由于无法看到具体代码,只能提供一般性建议。 如果问题仍然存在,请检查第33、38、46行附近的代码,确保系统任务的正确使用。 如果这些行不是系统任务,而是其他以`$`开头的标识符(例如宏定义),请注意在Verilog中,宏定义使用` `define`,使用时用` `标识符`,而不是`$`。 例如: ```verilog `define MAX 100 // 定义宏 reg [7:0] data = `MAX; // 使用宏,注意是反引号 ``` 如果错误行是宏的使用,请确保使用反引号(`)而不是美元符号($)。 由于错误信息中提到了美元符号,所以很可能是将宏的使用写成了`$MAX`,而正确的是`` `MAX ``。 因此,请检查代码中是否有类似`$display`、`$finish`等系统任务的错误拼写,或者是否错误地使用了`$`来引用宏(应该用反引号)。 如果确认是宏定义的问题,修改为反引号即可。 如果问题仍然无法解决,请提供具体的错误行代码,以便进一步分析。 由于问题描述中没有给出具体的代码行,我只能提供这些通用解决方案。 如果上述建议不能解决问题,请检查以下内容: 1. 确保测试文件(.vt)的扩展名是.v或者.sv(SystemVerilog),并且仿真工具支持该语法。 2. 检查测试文件中的每一行,特别是第33、38、46行,看是否有语法错误。 最后,如果问题仍然存在,请提供这些行的代码,以便更准确地定位问题。 由于没有具体代码,无法提供更具体的修复,但以上建议应该覆盖了大多数常见情况。 相关问题: §§相关问题§§: 1. 在Verilog测试平台中,如何正确使用$display系统任务来打印变量值? 2. 如何避免在Verilog测试平台中因系统任务使用不当而导致的编译错误? 3. 在ModelSim仿真中,常见的系统任务有哪些?它们的功能是什么? 4. 如何用宏定义在Verilog中定义常量?使用时需要注意什么?</think>### 错误分析与解决方案 根据您提供的错误信息,问题主要出现在测试文件(try.vt)中,错误提示是"$"符号附近的语法错误。这表明在测试平台中使用了不正确的系统任务或函数调用。我将为您提供一个完整的修复方案。 ### 错误原因分析 1. **语法错误**: - 在测试文件中使用了`$`开头的系统任务(如`$display`, `$finish`等),但语法不正确 - 可能是缺少分号、括号不匹配或任务名称拼写错误 2. **测试平台问题**: - 错误发生在测试文件(try.vt)而非设计文件 - 模型仿真的vlog工具无法编译测试平台 3. **常见错误场景**: - 使用`$display`或`$monitor`时格式字符串错误 - `$finish`或`$stop`调用方式不正确 - 在模块外部使用系统任务 ### 修复后的测试平台代码 ```verilog // try.vt - 修复后的测试平台 `timescale 1ns/1ps module test_try; // 1. 定义输入输出信号 reg clk; reg reset_n; wire clk_sensor; wire clk_st; wire flag; // 2. 实例化被测模块 try dut ( .clk(clk), .reset_n(reset_n), .clk_sensor(clk_sensor), .clk_st(clk_st), .flag(flag) ); // 3. 时钟生成(50MHz) initial begin clk = 0; forever #10 clk = ~clk; // 50MHz = 20ns周期 end // 4. 测试序列 initial begin // 初始化 reset_n = 0; #100; // 保持复位100ns // 释放复位 reset_n = 1; #200; // 监视信号变化 $display("======================================"); $display("Simulation started at time %0d ns", $time); $display("======================================"); // 等待标志信号 @(posedge flag); $display("Flag asserted at time %0d ns", $time); // 运行一段时间 #5000; // 结束仿真 $display("======================================"); $display("Simulation finished at time %0d ns", $time); $display("======================================"); $finish; end // 5. 波形记录 initial begin $dumpfile("waveform.vcd"); $dumpvars(0, test_try); end endmodule ``` ### 关键修复点说明 1. **正确的系统任务语法**: ```verilog // 错误示例(缺少分号或括号) $display("Time is " $time) // 正确语法 $display("Time is %0d", $time); ``` 2. **完整的测试平台结构**: - 包含`timescale`指令 - 正确定义输入输出信号 - 正确实例化被测模块 - 使用`initial`块初始化信号 3. **正确的系统任务使用**: - `$display`:带格式字符串和参数 - `$finish`:正确结束仿真 - `$dumpvars`:正确设置波形记录 4. **时序控制**: - 使用`#`延时控制 - 使用`@(posedge)`事件触发 ### 常见错误及修复表 | 错误类型 | 错误示例 | 正确写法 | |----------|----------|----------| | 缺少分号 | `$display("Hello")` | `$display("Hello");` | | 格式错误 | `$display("Time:" $time)` | `$display("Time: %0d", $time);` | | 任务位置 | 模块外部使用`$finish` | 在`initial`块内使用 | | 信号引用 | `$display(clk)` | `$display("clk = %b", clk);` | | 结束仿真 | `$stop` | `$finish;` | ### ModelSim 编译和运行步骤 1. 保存修复后的测试文件(如`test_try.v`) 2. 在ModelSim命令行中: ```bash # 创建工作库 vlib work # 编译设计文件 vlog try.v # 编译测试文件 vlog test_try.v # 启动仿真 vsim work.test_try # 运行仿真 run -all ``` ### 测试平台功能说明 1. **信号监视**: - 使用`$display`在关键点打印信息 - 显示仿真时间和信号状态 2. **波形记录**: ```verilog $dumpfile("waveform.vcd"); $dumpvars(0, test_try); ``` - 生成VCD波形文件用于调试 3. **测试序列**: - 复位初始化 - 释放复位 - 检测flag信号 - 自动结束仿真 ### 扩展建议 如果问题仍然存在,建议添加以下调试代码: ```verilog // 添加在测试平台中 always @(posedge clk_sensor) begin $display("CLK_SENSOR=%b, CLK_ST=%b, FLAG=%b at time %0d", clk_sensor, clk_st, flag, $time); end ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值