Socket 编程 UDP
目录
1. UDP网络编程
1.1 echo server
1.1.1 接口
1.1.1.1 创建套接字
1.1.1.2 绑定
1.1.1.3 bzero
1.1.1.4 htons(主机序列转网络序列)
1.1.1.5 inet_addr(主机序列IP转网络序列IP)
1.1.1.6 recvfrom(让服务器收消息)
1.1.1.7 sendto(写消息)
1.1.1.8 netstat -uap(查看网络服务是否启动)
1.1.1.9 client不需要bind问题
1.1.1.10 inet_ntoa(网络序列IP转主机序列IP)
1.1.1.11 云服务器禁止bind公网IP
1.1.1.12 inet_ntop(网络序列IP转主机序列IP)
1.1.2 代码
1.1.2.1 Version 1
1.1.2.2 Version 2
1.1.2.3 Version 3
1.2 DictServer
1.3 简单聊天室
1.4 补充参考内容
1.4.1 地址转换函数
1.4.2 关于inet_ntoa
2. 网络命令
2.1 Ping命令
2.2 netstat命令
2.2.1 查看UDP
2.2.2 查看TCP
2.2.3 watch指令
2.3 pidof命令
3. 验证UDP - windows作为client访问Linux
1. UDP网络编程
1.1 echo server
1.1.1 接口
1.1.1.1 创建套接字
// man socketNAMEsocket - create an endpoint for communication// 创建一个套接字SYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>int socket(int domain, int type, int protocol);// domain:域,协议族,协议家族的类型
Name Purpose Man page
AF_UNIX Local communication unix(7) // 本地通信
AF_LOCAL Synonym for AF_UNIX
AF_INET IPv4 Internet protocols ip(7) // 网络通信
AF_INET6 IPv6 Internet protocols ipv6(7) // IPv6暂时不考虑// type:类型,代表想要创建什么样的套接字
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data transmission mechanism may be supported. // TCP
SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixed maximum length). // UDP// protocol:创建的套接字,传输层的类型用哪一个,TCP还是UDP,但我们不用传这个参数,这个参数
// 默认为0就可以了,因为只要是网络的,类型是数据报套接字,socket创建出来默认就是UDP套接字。
// 后面用的时候设置为0就可以了// 返回值:
RETURN VALUEOn success, a file descriptor for the new socket is returned. On error, -1 is returned, and errno is set appropriately.
返回的是文件的描述符,本质是创建了一个文件,创建文件描述符,创建struct file对象,struct file的操作函数初始化。aurora@wanghao:~/Linux/2025_05_19_EchoServer$ ./server_udp
[2025-05-19 19:18:33] [INFO] [159814] [UdpServer.hpp] [38] - socket success,sockfd is : 3
// 编译运行之后,文件描述符的数字是3
1.1.1.2 绑定
// man bindNAMEbind - bind a name to a socket // 给套接字绑定名字SYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);// sockfd:绑定套接字,传递创建的文件描述符
// addr:sockaddr_in
// 结构体所对应的长度// 返回值:
RETURN VALUEOn success, zero is returned. On error, -1 is returned, and errno is set appropriately.
// 绑定成功,0返回,否则-1被返回//sockaddr_in man inet_addrstruct sockaddr_in
{__SOCKADDR_COMMON (sin_);in_port_t sin_port; /* Port number. */struct in_addr sin_addr; /* Internet address. *//* Pad to size of `struct sockaddr'. */unsigned char sin_zero[sizeof (struct sockaddr)- __SOCKADDR_COMMON_SIZE- sizeof (in_port_t)- sizeof (struct in_addr)];
};
1.1.1.3 bzero
struct sockaddr_in local;
bzero(&local,sizeof(local));
local.sin_family = AF_INET;
sockaddr_in里面是有填充字段的,所以我们追求locak本身的确定性,所以我们建议清零,然后再进行填充。
// man bzeroNAMEbzero, explicit_bzero - zero a byte string // 把传进来的字符串全部清零
SYNOPSIS#include <strings.h>void bzero(void *s, size_t n);
1.1.1.4 htons(主机序列转网络序列)
// man htonsNAMEhtonl, htons, ntohl, ntohs - convert values between host and network byte order// 本地的序列转换成网络的序列SYNOPSIS#include <arpa/inet.h>uint16_t htons(uint16_t hostshort);
现在有一台服务器,将来别人是给这个服务器发消息的,那么未来这个服务器肯定也是要给别人回消息的,作为服务器端或者客户端,我们的发的消息里面,一定会包含报头,而我们为了让别人能给我们把消息转回来,所以我的报头中一定要有我的源IP和源端口号,所以服务器一定是要把自己的IP地址和端口号也要推送给对方,因为要让对方知道我是谁,,它才可能把消息给我反回来。
port占两个字节,uint16_t,是本地的,所以这个port是大端的还是小端的不知道,所以要把port做主机序列转网络序列。本来就是大端的话也要转一下,因为你不知道你的代码将来在哪个机器下跑,为了代码的可移植性。所以port要由我们的主机序列转换成网络序列。然后才能设置进sin_port。
local.sin_port = htons(_port); // 要被发生给对方的,即要发到网络中!
1.1.1.5 inet_addr(主机序列IP转网络序列IP)
IP的话有点复杂,点分十进制的IP,首先把字符串风格的IP转换成4字节的,然后把4字节的IP转换成网络序列,起始也就是大端。
// man inet_addrNAMEinet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation rou‐tinesSYNOPSIS#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>int inet_aton(const char *cp, struct in_addr *inp);in_addr_t inet_addr(const char *cp); // 把一个字符串风格的IP地址转成4字节IP// 同时把4字节IP地址转换成网络序列。in_addr_t inet_network(const char *cp);char *inet_ntoa(struct in_addr in);struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);in_addr_t inet_lnaof(struct in_addr in);in_addr_t inet_netof(struct in_addr in);
// 这些接口,要么是把字符串转成4字节,同时转成网络序列,要么是把4字节,转成主机序列,同时转成字符串。
local.sin_addr = ::inet_addr(_ip.c_str()); // 1.string ip -> 4bytes 2. network order
如果我们这样写的话会报错的,首先我们看一下sockaddr_in中有什么东西。
struct sockaddr_in
{__SOCKADDR_COMMON (sin_);in_port_t sin_port; /* Port number. */struct in_addr sin_addr; /* Internet address. *//* Pad to size of `struct sockaddr'. */unsigned char sin_zero[sizeof (struct sockaddr)- __SOCKADDR_COMMON_SIZE- sizeof (in_port_t)- sizeof (struct in_addr)];
};
后面的为填充字段,但是我们可以看到sin_addr是结构体类型的,那我们再进去看一下,这个结构体里面有什么东西。
/* Internet address. */
typedef uint32_t in_addr_t;
struct in_addr
{in_addr_t s_addr;
};
它的里面有一个叫做s_addr的变量,因为在C语言当中,结构体只能被整体初始化,不能被整体赋值,所以我们对结构体赋值就得一个一个的赋值。
local.sin_addr.s_addr = ::inet_addr(_ip.c_str()); // 1.string ip -> 4bytes 2. network order
所以我们要这样写。
还有一个问题,在结构体中怎么部件协议族,也就是sin_family。
1.1.1.6 recvfrom(让服务器收消息)
// man recvfromNAMErecv, recvfrom, recvmsg - receive a message from a socketSYNOPSIS#include <sys/types.h>#include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);// 从指定的套接字处直接收消息,收到的消息放在buf中,期望收消息收多少字节用len表示,flags表示收的方式,为0就行,我们以阻塞的方式收,实际收到了多少字节由返回值决定,返回值大于0读取成功,小于0读取失败。// 后两个参数的意思就是我们要知道是谁给我们发的消息,标识另一端就用IP+端口号
// 是输出型参数
struct sockaddr_in peer;
socklen_t len = sizeof(peer)RETURN VALUEThese calls return the number of bytes received, or -1 if an error occurred. In the event of an error, errno is set to in‐dicate the error.
// 如果成功,就返回督导的多少字节数,否则-1返回
1.1.1.7 sendto(写消息)
// man sendtoNAMEsend, sendto, sendmsg - send a message on a socketSYNOPSIS#include <sys/types.h>#include <sys/socket.h>ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);// sockfd:未来创建好的一个socket fd,即可以发,也可以收,这种我们称为全双工。
// 管道的文件描述符只能读,或者只能写,这个叫半双工。
// 半双工是任何一个时刻只能一端向另一端发,管道是特殊的半双工,只能一端向另一端发,反过来不行// buf && len :发送的字符串// flags:发送的方式,设置为0,阻塞的方式发// dest_addr && addrlen:目标主机的进程
1.1.1.8 netstat -uap(查看网络服务是否启动)
aurora@wanghao:~/Linux/2025_05_19_EchoServer$ netstat -uap
(Not all processes could be identified, non-owned process infowill not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
udp 0 0 wanghao:8080 0.0.0.0:* 161017/./server_udp
udp 0 0 localhost:domain 0.0.0.0:* -
udp 0 0 wanghao:bootpc 0.0.0.0:* -
udp 0 0 wanghao:323 0.0.0.0:* -
udp6 0 0 localhost:323 [::]:* - -
- u:UDP的意思
- a:all全部的意思
- p:pid
不带p就少一列,带上p就多一列,顺序随便写。
aurora@wanghao:~/Linux/2025_05_19_EchoServer$ netstat -nuap
(Not all processes could be identified, non-owned process infowill not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
udp 0 0 127.0.0.1:8080 0.0.0.0:* 161728/./server_udp
udp 0 0 127.0.0.53:53 0.0.0.0:* -
udp 0 0 172.26.160.193:68 0.0.0.0:* -
udp 0 0 127.0.0.1:323 0.0.0.0:* -
udp6 0 0 ::1:323 :::* -
- n:能显示成数字的全部显示成数字
- 0.0.0.0:*:就是允许任何远端向我发消息
- 161728/./server_udp :进程以及服务器名字
- 什么叫网络服务?
网络服务就是一个进程、或者进程池、或者一堆进程、或者一堆线程- 客户端主动,服务器被动,服务器一直等客户端,这种模式叫做CS模式,C:client、S:server
1.1.1.9 client不需要bind问题
1. client 不需要bind吗?
客户端也要有自己的ip和端口,但是客户端不需要自己显示的调用bind!!而是客户端首次sendto消息的时候,由OS自动bind。
2. 如何理解客户端自动bind?
首先客户端对应的ip地址都是固定的,关键在于客户端要自动绑定的话就要自动填充自己的sockaddr_in结构、ip地址、端口号、协议族,然后把客户端信息想办法发送给服务的,服务器才能知道客户点是谁如果再我们的服务器里面,存在很多的端口号,也存在很多的进程,一个端口号只能被一个进程绑定,一个端口号不允许被多个进程绑定的,操作系统也不允许,因为操作系统收到报文要根据端口号查进程,所以端口号到进程必须具有唯一性,所以,一个端口号只能被一个进程绑定,反过来,一个进程是可以绑定多个端口号的,如果客户端实现的绑定端口号的话,会带来一个后果不同公司的客户端之间会互相冲突,比如说淘宝先启动了,抖音就跑不起来了,因为淘宝和抖音使用一个端口号,势必这两个 是不能同时启动的,bind就失败,所以对于客户端,我们要做的是让操作系统自动随机绑定端口号。
3. 如何理解server要显示的bind?
服务器的端口号必须稳定,必须是众所周知且不能轻易改变的!
1.1.1.10 inet_ntoa(网络序列IP转主机序列IP)
// man inet_ntoaNAMEinet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation rou‐tinesSYNOPSIS#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>char *inet_ntoa(struct in_addr in); // 把4字节ip地址既转成主机序列,然后又转成字符串
1.1.1.11 云服务器禁止bind公网IP
服务器再绑定的时候我们发现绑定失败了,服务器在绑定的时候端口号可以自由指定,ip地址原则上可以自由指定,但有点违和,ip地址本来就是属于自己的机器啊,和进程有什么关系呢?进程拿着端口号来确定进程的唯一性就可以了,关ip地址什么事情,那127.0.0.1怎么能绑呢?
- 云服务器,禁止用户bind公网ip,因为112.126.76.148这个ip就不属于你这个机器,是通过一系列的云产品虚拟出来的ip地址。
最多只能绑图片中的两个,第一个是内网ip,第二个是本地环回的ip。
- 虚拟机,可以bind你的任何IP。
又的服务器上不止一个IP,你也可以理解成通过虚拟化技术虚拟出来的,也可以认为不止一张网卡,只要你绑定了对应的IP,也就是说你只能得到绑定的ip得到的报文,别的收不到,所以服务器不需要bindIP,只需要端口号就可以了。
local.sin_addr.s_addr = INADDR_ANY;/* Address to accept any incoming messages. */
#define INADDR_ANY ((in_addr_t) 0x00000000)
我们只需要将s_addr设置为INADDR_ANY,INADDR_ANY其实是0,也就是说设置为INADDR_ANY表示我的服务器可以接收来自这个主机上的所有IP的报文。只要发过来的端口号是我指定的端口号就行。
0.0.0.0.0的意思是任意IP绑定,只要是发给这台机器上的,不论从哪个IP地址收到的报文,只要端口号填的8888,都给我。
1.1.1.12 inet_ntop(网络序列IP转主机序列IP)
// man inet_ntopNAMEinet_ntop - convert IPv4 and IPv6 addresses from binary to text formSYNOPSIS#include <arpa/inet.h>const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);// af:协议族
// src:源数据
// dst && size:目标缓冲区起始地址和长度// 所以我们要定义一个缓冲区传进去,不存在多线程安全问题,因为缓冲区在栈上定义的话属于线程内部的
//man inet_ntoaNAMEinet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation rou‐tines
SYNOPSIS#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>char *inet_ntoa(struct in_addr in);
这两个方法都是可以的,为什么不太想用第二个呢?
第二个确实是把一个四字节转成一个字符串,但是这里会有一个问题,他返回的是char*,不是字符串,C语言中没有字符串类型,它既然返回char*的话,那么字符串在哪里呢?我们一定要小心返回值为指针的东西,因为inat_ntoa在内部会维护一段静态空间,既然是静态空间的话,此时在静态空间当中进行使用inat_ntoa的时候,返回这个char*,那么有可能在多线程环境当中使用就会出现下一个操作会把上一个覆盖的问题,所以这个函数不太安全,而我们还是习惯用inat_ntop。
1.1.2 代码
1.1.2.1 Version 1
Linux: This repository is specifically designed to store Linux code - Gitee.comhttps://gitee.com/Axurea/linux/tree/master/2025_05_19_EchoServer该代码实现了本地通信。
这个代码至少能完成本地通信,UDP虽然不保证可靠性,但我们在本地通信中它不会丢失的,因为没有经过网络,所以这个时候就可以理解进程间通信不要搞太多,因为有TCP/UDP就够用了。
1.1.2.2 Version 2
Linux: This repository is specifically designed to store Linux code - Gitee.comhttps://gitee.com/Axurea/linux/tree/master/2025_05_20_EchoServer在Version1的基础上增加了网络的通信。
1.1.2.3 Version 3
Linux: This repository is specifically designed to store Linux code - Gitee.comhttps://gitee.com/Axurea/linux/tree/master/2025_05_21_EchoServer在version2的基础上对IP地址和端口之间的转换做了封装。
1.2 DictServer
Linux: This repository is specifically designed to store Linux code - Gitee.comhttps://gitee.com/Axurea/linux/tree/master/2025_05_20_DictServer
1.3 简单聊天室
Linux: This repository is specifically designed to store Linux code - Gitee.com
聊天本质上就是观察者模型,发消息把消息推送给所有人,而我推送给那些人呢?推送给了关心这条消息的人,所谓的观察者就是观察这个群里有没有事件,有没有消息,如果有消息就推送给所有人,消息转发的本质就是生产消费者模型,因为线程池是一个生产消费模型,我们在进行生产消费过程中,我们不能只关心把任务放入到任务队列,消费者从任务队列中拿走。
在我们对应的消费者在进行任务处理的时候,在进行把任务放入任务队列之前,要做读取数据,获取任务,生产者把任务队列拿走了,拿走了不是光拿走,这不是消费,拿走之后还要基于observer观察者模式,推送消息给所有人。
1.4 补充参考内容
1.4.1 地址转换函数
本博客只介绍基于IPv4的socket网络编程,sockaddr_in中的成员struct in_addr sin_addr表示32位的IP地址。
但是我们通常用点分十进制的字符串表示IP地址,以下函数可以在字符串表示和in_addr表示之间的转换:
字符串转in_addr的函数:
#include <arpa/inet.h>int inet_aton(const char *cp, struct in_addr *inp);in_addr_t inet_addr(const char *cp);
in_addr转字符串的函数:
char *inet_ntoa(struct in_addr in);
const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);
其中inet_pton和inet_ntop不仅可以转换IPv4的in_addr,还可以转换IPv6的in6_addr,因此函数接口是void *addrptr。
代码示例:
#include <stdio.h>
#include<sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>int main()
{struct sockaddr_in addr;inet_aton("127.0.0.1",&addr.sin_addr);uint32_t* ptr = (uint32_t*)(&addr.sin_addr);printf("addr: %x\n",*ptr);printf("addr_str: %s\n",inet_ntoa(addr.sin_addr));return 0;
}
1.4.2 关于inet_ntoa
inet_ntoa这个函数返回一个char*,很显然是这个函数自己在内部为沃尔玛申请了一块内存来保存ip的结构,那么是否需要调用者手动释放呢?
The inet_ntoa() function converts the Internet host address in,
given in network byte order, to a string in IPv4 dotted-decimal notation.
The string is returned in a statically allocated buffer, which subsequent calls will overwrite.
man手册上说,inet_ntoa函数,是把这个返回结果放到了静态存储区,这个时候不需要我们手动进行释放。
那么问题来了,如果我们调用多次这个函数,会有什么样的效果呢?
#include <stdio.h>
#include<sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>int main()
{struct sockaddr_in addr1;struct sockaddr_in addr2;addr1.sin_addr.s_addr = 0;addr2.sin_addr.s_addr = 0xffffffff;char* ptr1 = inet_ntoa(addr1.sin_addr);char* ptr2 = inet_ntoa(addr2.sin_addr);printf("ptr1: %s, ptr2: %s\n",ptr1,ptr2);return 0;
}
运行结果如下:
因为inet_ntoa把结果放到自己内部的一个静态存储区,这样第二次调用时的结果会覆盖掉上一次的结果。
- 思考:如果有多个线程调用inet_ntoa,是否会出现异常情况呢?
- 在APUE中,明确提出inet_ntoa不是线程安全的函数。
- 但是在centos7上测试,并没有出现问题,可能内部的实现加了互斥锁。
- 我们也可以写程序验证以下在自己的机器上inet_ntoa是否会出现多线程的问题。
- 在多线程环境下,推荐使用inet_ntop,这个函数由调用者提供一个缓冲区保存结果,可以规避线程安全问题。
多线程调用inet_ntoa代码示例如下:
#include <stdio.h>
#include <unistd.h>
#include<sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>void* Func1(void* p)
{struct sockaddr_in* addr = (struct sockaddr_in*)p;while(1){char* ptr = inet_ntoa(addr->sin_addr);printf("addr1: %s\n",ptr);}return NULL;
}void* Func2(void* p)
{struct sockaddr_in* addr = (struct sockaddr_in*)p;while(1){char* ptr = inet_ntoa(addr->sin_addr);printf("addr2: %s\n",ptr);}return NULL;
}int main()
{pthread_t tid1 = 0;struct sockaddr_in addr1;struct sockaddr_in addr2;addr1.sin_addr.s_addr = 0;addr2.sin_addr.s_addr = 0xffffffff;pthread_create(&tid1,NULL,Func1,&addr1);pthread_t tid2 = 0;pthread_create(&tid2,NULL,Func2,&addr2);pthread_join(tid1,NULL);pthread_join(tid2,NULL);return 0;
}
2. 网络命令
2.1 Ping命令
ping命令主要是用来检测网络连通性的一条命令。
aurora@wanghao:~/test$ ping www.baidu.com
PING www.a.shifen.com (220.181.111.232) 56(84) bytes of data.
64 bytes from 220.181.111.232 (220.181.111.232): icmp_seq=1 ttl=51 time=4.20 ms
64 bytes from 220.181.111.232 (220.181.111.232): icmp_seq=2 ttl=51 time=4.18 ms
64 bytes from 220.181.111.232 (220.181.111.232): icmp_seq=3 ttl=51 time=4.19 ms
64 bytes from 220.181.111.232 (220.181.111.232): icmp_seq=4 ttl=51 time=4.20 ms
^C
--- www.a.shifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 4.177/4.190/4.203/0.009 ms
比如说我写了一个服务,一直给发消息但得不到响应,那么我们就先可以ping一下,看一下网络有没有连通。如果网络能连通,那么就说明我们的服务器本身写的有问题。ping命令一旦开始,是不会停止的,我们可以指定ping的次数。
ping -c1 www.baidu.com//c可以理解为count的意思
aurora@wanghao:~/test$ ping -c 1 www.baidu.com
PING www.a.shifen.com (220.181.111.232) 56(84) bytes of data.
64 bytes from 220.181.111.232 (220.181.111.232): icmp_seq=1 ttl=51 time=4.17 ms--- www.a.shifen.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 4.174/4.174/4.174/0.000 m
ping命令可以看到结果即可证明我们的网络是连通的。
2.2 netstat命令
netstat命令是用来查看网络服务的命令。
语法:netstat[选项]
功能:查看网络状态
我们编写的后端的UDP、TCP相关的网络服务最终启动起来就是一个进程,但这个进程我们用ps能查到这个进程,但智能查到比较偏向于进程相关的一些属性字段,而我想看一看更多关于网络方面的一些属性字段就可以用netstat命令。
常用选项:
- n拒绝显示别名,能显示数字的全部转化成数字
- I仅列出有在Listen(监听)的服务状态
- p显示建立相关链接的程序名
- t(tcp)仅显示tcp相关选项
- u(udp)仅显示udp相关选项
- a(all)显示所有选项,默认不显示LISTEN相关
2.2.1 查看UDP
netstat默认去查,它会把我们能看到的比如TCP的UDP的,还有域间套接的,都可以看到,可是我们今天就想看UDP的。
那下面的怎么是空的,查不到呢?
有些端口不允许普通进程去绑定的,比如80,443,启动时,需要采用超级用户权限来启动,我们之所以能查到,是因为这个网络进程是我用普通用户来启动的,就能查到我启动的,但是其他服务很明显是系统本身自己自启动的,或者其他人启动的,我们能看到当前的网络服务,但是信息是看不到的。
要想看到,就带sudo。
不想看到主机名称,想要看到IP地址,就带n选项。n可以理解成num的意思。
这几个选项的顺序无所谓,都不影响查看的最终结果。
2.2.2 查看TCP
凡是协议是TCP的就全部会显示出来。
查看所有处于LISTEN状态的所有服务。l就是LISTEN的意思。
不要显示主机名,显示成数字,带上n。
带上p就可以查看进程相关的部分了,短杠部分和我们前面的UDP是一样的。选项的顺序可以随便去写。
2.2.3 watch指令
watch指令是一个周期性执行linux命令的任务。
// 每隔1s执行一次netstat -nltp
watch -n 1 netstat -nltp// n表示刷新的次数
时间其实在走,ctrl + c终止。
2.3 pidof命令
pidof命令是用来查看特定网络服务对应的进行pid的命令。在查看服务器的进程id时非常方便。
语法:pidof[进程名]
功能:通过进程名,查看进程id
这样拿也没问题,我们ctrl + c也可以,但是有的进程是后台进程或者守护进程,那么我们就得拿到进程的pid了,kill -9 进程pid,可是这样的方法,1要查,2要杀,会比较慢,我们更好的做法就是pidof。
这样我们就可以杀掉对应的服务了,这里的xargs,管道是个文件,当我们pidof把pid通过管道传给kill命令时,实际上这个kill命令是通过自己的标准输入文件描述符0来把数据读到kill里面的,很显然,kill命令要杀一个进程一定是把pid,放在自己的命令行参数当中传给kill命令。
xargs的作用就是把管道当中传递过来的数据转化成后续的命令行参数,拼接到后面,所有我们就可以采用命令组合的方式来杀进程。
3. 验证UDP - windows作为client访问Linux
Linux: This repository is specifically designed to store Linux code - Gitee.comhttps://gitee.com/Axurea/linux/tree/master/2025_05_26_Udp_WindowsClient&&LinxuServer
注意:一定要开放云服务器对应的端口号,在你的阿里云或者腾讯云、华为云的网站后台中开放。
我们可以发现udp client(windows)和udp server(Linux)可以通信。
WinSock2.h是Windows Sockets API(应用程序接口)的头文件,用于在Windows平台上进行网络编程。它包含了Windows Sockets 2(WinSock2)所需的数据类型、函数声明和结构定义,使得开发者能够创建和使用套接字(sockets)进行网络通信。
在编写使用Winsock2的程序时,需要在源文件中包含WinSock2.h头文件。这样,编译器就能够识别并理解Winsock2中定义的数据类型和函数,从而能够正确的编译和链接网络相关的代码。
此外,与WinSock2.h头文件相对应的是ws2_32.lib库文件。在链接阶段,需要将这个库文件链接到程序中,以确保运行时能够找到并调用Winsock2 API中实现的函数。
在WinSock2.h中定义了一些重要的数据类型和函数,如:
WSADATA:保存初始化Winsock库时返回的信息。
SOCKET:表示一个套接字描述符,用于在网络中唯一标识一个套接字。
sockaddr_in:IPv4地址结构体,用于存储IP地址和端口号等信息。
socket():创建一个套接字。
bind():将套接字与本地地址绑定。
listen():将套接字设置为监听模式,等待客户端的连接请求。
accept():接受客户端的连接请求,并返回一个新的套接字描述符,用于与客户端
进行通信。
WSAStartup函数是Windows Sockets API的初始化函数,它用于初始化Winsock库。该函数在应用程序或DLL调用任何Windows套接字函数之前必须首先执行,它扮演着初始化的角色。
以下是WSAStartup函数的一些关键的:
它接受两个参数:wVersionRequested和IpWSAData。wVersionRequested用于指定所请求的Winsock版本,通常使用MAKEWORD(major,minor)宏,其中major和minor分别标识请求的主版本号和次版本号。IpWSAData是一个指向WSAData结构的指针用于接收初始化信息。
如果函数调用成功,它会返回0:否则,返回错误代码。
WSAStartup函数的主要作用是向操作系统说明我们将使用哪个版本的Winsock库,从而使得该库文件能与当前的操作系统协同工作。成功调用该函数后,Winsock库的状态会被初始化,应用程序就可以使用Winsock提供的一系列套接字服务,如地址家族识别、地址转换、名字查询和连接控制等。这些服务使得应用程序可以与底层的网络协议栈进行交互,实现网络通信。
在调用WSAStartup函数后,如果应用程序完成了对请求的Socket库的使用,应调用
WSAStartup函数后,如果应用程序完成了对请求的Socket库的使用,应调用WSACleanup
函数来解除与Socket库的绑定并释放所占用的系统资源。
相关文章:

Socket 编程 UDP
目录 1. UDP网络编程 1.1 echo server 1.1.1 接口 1.1.1.1 创建套接字 1.1.1.2 绑定 1.1.1.3 bzero 1.1.1.4 htons(主机序列转网络序列) 1.1.1.5 inet_addr(主机序列IP转网络序列IP) 1.1.1.6 recvfrom(让服务…...

Jenkins实践(8):服务器A通过SSH调用服务器B执行Python自动化脚本
Jenkins实践(8):服务器A通过SSH调用服务器B执行Python自动化脚本 1、需求: 1、Jenkins服务器在74上,Python脚本在196服务器上 2、需要在服务器74的Jenkins上调用196上的脚本执行Python自动化测试 2、操作步骤 第一步:Linux Centos7配置SSH免密登录 Linux Centos7配置S…...
Spring AI系列之Spring AI 集成 ChromaDB 向量数据库
1. 概述 在传统数据库中,我们通常依赖精确的关键词或基本的模式匹配来实现搜索功能。虽然这种方法对于简单的应用程序已经足够,但它无法真正理解自然语言查询背后的含义和上下文。 向量存储解决了这一限制,它通过将数据以数值向量的形式存储…...

lua的注意事项2
总之,下面的返回值不是10,a,b 而且...
主流电商平台的反爬机制解析
随着数据成为商业决策的重要资源,越来越多企业和开发者希望通过技术手段获取电商平台的公开信息,用于竞品分析、价格监控、市场调研等。然而,主流电商平台如京东、淘宝(含天猫)等为了保护数据安全和用户体验࿰…...

前端八股之HTML
前端秘籍-HTML篇 1. src和href的区别 src 用于替换当前元素,href 用于在当前文档和引用资源之间确立联系。 (1)src src 是 source 的缩写,指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置࿱…...
tiktoken学习
1.tiktoken是OpenAI编写的进行高效分词操作的库文件。 2.操作过程: enc tiktoken.get_encoding("gpt2") train_ids enc.encode_ordinary(train_data) val_ids enc.encode_ordinary(val_data) 以这段代码为例,get_encoding是创建了一个En…...

鲲鹏Arm+麒麟V10,国产化信创 K8s 离线部署保姆级教程
Rainbond V6 国产化部署教程,针对鲲鹏 CPU 麒麟 V10 的离线环境,手把手教你从环境准备到应用上线,所有依赖包提前打包好,步骤写成傻瓜式操作指南。别说技术团队了,照着文档一步步来,让你领导来都能独立完成…...
历年厦门大学计算机保研上机真题
2025厦门大学计算机保研上机真题 2024厦门大学计算机保研上机真题 2023厦门大学计算机保研上机真题 在线测评链接:https://pgcode.cn/school 数字变换过程的最大值与步数 题目描述 输入一个数字 n n n,如果 n n n 是偶数就将该偶数除以 2 2 2&…...

【C++ Qt】认识Qt、Qt 项目搭建流程(图文并茂、通俗易懂)
每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” 绪论: 本章将开启Qt的学习,Qt是一个较为古老但仍然在GUI图形化界面设计中有着举足轻重的地位,因为它适合嵌入式和多种平台而被广泛使用…...

IoT/HCIP实验-1/物联网开发平台实验Part2(HCIP-IoT实验手册版)
文章目录 概述产品和设备实例的产品和设备产品和设备的关联单个产品有多个设备为产品创建多个设备产品模型和物模型设备影子(远程代理) 新建产品模型定义编解码插件开发编解码插件工作原理消息类型与二进制码流添加消息(数据上报消息…...

Replacing iptables with eBPF in Kubernetes with Cilium
source: https://archive.fosdem.org/2020/schedule/event/replacing_iptables_with_ebpf/attachments/slides/3622/export/events/attachments/replacing_iptables_with_ebpf/slides/3622/Cilium_FOSDEM_2020.pdf 使用Cilium,结合eBPF、Envoy、Istio和Hubble等技术…...
推荐系统排序指标:MRR、MAP和NDCG
文章目录 MRR: Mean Reciprocal RankMAP: Mean Average PrecisionNDCG: Normalized Discounted Cumulative Gain3个度量标准来自于两个度量家族。第一种度量包括基于二进制相关性的度量。这些度量标准关心的是一个物品在二进制意义上是否是好的。第二个系列包含基于应用的度量。…...

数学建模之最短路径问题
1 问题的提出 这个是我们的所要写的题目,我们要用LINGO编程进行编写这个题目,那么就是需要进行思考这个怎么进行构建这个问题的模型 首先起点,中间点,终点我们要对这个进行设计 2 三个点的设计 起点的设计 起点就是我们进去&am…...

测试概念 和 bug
一 敏捷模型 在面对在开发项目时会遇到客户变更需求以及合并新的需求带来的高成本和时间 出现的敏捷模型 敏捷宣言 个人与交互重于过程与工具 强调有效的沟通 可用的软件重于完备的文档 强调轻文档重产出 客户协作重于合同谈判 主动及时了解当下的要求 相应变化…...

zynq 级联多个ssd方案设计(ECAM BUG修改)
本文讲解采用zynq7045芯片如何实现200T容量高速存储方案设计,对于大容量高速存储卡,首先会想到采用pcie switch级联方式,因为单张ssd的容量是有限制的(目前常见的m.2接口容量为4TB,U.2接口容量为16TB)&…...

brep2seq 论文笔记
Brep2Seq: a dataset and hierarchical deep learning network for reconstruction and generation of computer-aided design models | Journal of Computational Design and Engineering | Oxford Academic 这段文本描述了一个多头自注意力机制(MultiHead Attenti…...

【运维实战】Linux 中设置 sudo ,8个有用的 sudoers 配置!
在Linux及其他类Unix操作系统中,只有 root 用户能够执行所有命令并进行关键系统操作,例如安装更新软件包、删除程序、创建用户与用户组、修改重要系统配置文件等。 但担任 root 角色的系统管理员可通过配置sudo命令,允许普通系统用户执行特定…...
Ad Hoc
什么是 Ad Hoc? Ad hoc 一词源于拉丁语,意为“为此目的”或“为此特定原因”。一般来讲,它指的是为解决某一特定问题或任务(而非为了广泛重复应用)而设计的行动、解决方案或组合。在加密货币和区块链领域,…...

江科大SPI串行外设接口hal库实现
hal库相关函数 初始化结构体 typedef struct {uint32_t Mode; /*SPI模式*/uint32_t Direction; /*SPI方向*/uint32_t DataSize; /*数据大小*/uint32_t CLKPolarity; /*时钟默认极性控制CPOL*/uint32_t CLKPhase; /*…...

[网页五子棋][对战模块]前后端交互接口(建立连接、连接响应、落子请求/响应),客户端开发(实现棋盘/棋子绘制)
文章目录 约定前后端交互接口建立连接建立连接响应针对"落子"的请求和响应 客户端开发实现棋盘/棋子绘制部分逻辑解释 约定前后端交互接口 对战模块和匹配模块使用的是两套逻辑,使用不同的 websocket 的路径进行处理,做到更好的耦合 建立连接 …...

【ArcGIS Pro微课1000例】0071:将无人机照片生成航线、轨迹点、坐标高程、方位角
文章目录 一、照片预览二、生成轨迹点三、照片信息四、查看方位角五、轨迹点连成线一、照片预览 数据位于配套实验数据包中的0071.rar,解压之后如下: 二、生成轨迹点 地理标记照片转点 (数据管理),用于根据存储在地理标记照片文件(.jpg 或 .tif)元数据中的 x、y 和 z 坐…...

Ubuntu Zabbix 钉钉报警
文章目录 概要Zabbix警监控脚本技术细节配置zabbix告警 概要 提示:本教程用于Ubuntu ,zabbix7.0 Zabbix警监控脚本 提示:需要创建一个脚本 #检查是否有 python3 和版本 rootzabbix:~# python3 --version Python 3.12.3在/usr/lib/zabbix/…...

threejs顶点UV坐标、纹理贴图
1. 创建纹理贴图 通过纹理贴图加载器TextureLoader的load()方法加载一张图片可以返回一个纹理对象Texture,纹理对象Texture可以作为模型材质颜色贴图.map属性的值。 const geometry new THREE.PlaneGeometry(200, 100); //纹理贴图加载器TextureLoader const te…...

STM32 RTC实时时钟\BKP备份寄存器\时间戳
一、Unix时间戳 想要计算当地北京时间,需要根据经度和闰年之类的运算得到(c语言里面可以调用time.h的函数) 二、UTC/GMT(科普) 三、时间戳转化 C语言的time.h模块提供了时间获取和时间戳转换的相关函数,可以方便的进行秒计数器、…...
springcloud---gateway
目录标题 理解gateway代码示例filter与aop的联系ServerWebExchangeReactor 的 Context那是隐式传递Map吗Context和ThreadLocalSpring 的 AOP 是用的什么为什么过滤器要用异步非阻塞,而 AOP 用同步阻塞?理解gateway 代码示例 import io.netty.channel.Channel; import lombo…...

Axure设计案例——科技感立体柱状图
想让你的数据展示告别平淡无奇,成为吸引全场目光的焦点吗?快来瞧瞧这个Axure设计的科技感立体柱状图案例!科技感设计风格借助逼真的立体效果打破传统柱状图的平面感,营造出一种令人眼前一亮的视觉震撼。每一个柱状体都仿佛是真实存…...

app获取相册权限是否意味着所有相片都可随时读取?
针对安卓手机相册的隐私安全问题,我也比较好奇,App授予了相册权限,真的能自动读取用户的照片吗?最近做了一个小实验,我开发了2个小App,这2个App安装的时候只授予了相册权限,没有授予其他任何权限…...

2025年05月29日Github流行趋势
项目名称:agenticSeek 项目地址url:https://github.com/Fosowl/agenticSeek项目语言:Python历史star数:11898今日star数:2379项目维护者:Fosowl, steveh8758, klimentij, ganeshnikhil, apps/copilot-pull-…...

第十一节:第一部分:正则表达式:应用案例、爬取信息、搜索替换
正则表达式介绍 String提供的正则表达式的方法的书写规则 正则表达式总结 正则表达式作用: 作用三:搜索替换 案例分析及代码(图片解析) 代码: 代码一:校验手机号和邮箱格式是否正确 package com.itheima.…...