实验目标:通过套接字和WSL,实现局域网内的通信。
c#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
printf("start sending message to server on 127.0.0.1:1324\n");
// 创建客户端套接字
int socketfd = socket(AF_INET, SOCK_DGRAM, 0);
if (socketfd == -1) {
perror("create socket failed: \n");
return -1;
}
// 创建服务器端地址
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(1324);
server_addr.sin_addr.s_addr = inet_addr("172.20.201.19");
// 开始发送数据
char* message = "Hello from client! \0";
ssize_t bytes_sent = sendto(socketfd, message, strlen(message), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (bytes_sent == -1) {
perror("sending message failed: \n");
close(socketfd);
return -1;
}
// 开始接收数据
char buffer[1024];
ssize_t bytes_recv = recvfrom(socketfd, buffer, sizeof(buffer), 0, NULL, NULL);
if (bytes_recv == -1) {
perror("receiving data failed: \n");
close(socketfd);
return -1;
}
printf("received from server:\n");
printCharArrayToHex(buffer, 1024);
// 关闭套接字
close(socketfd);
return 0;
}
// 将char数组中的内容按十六进制进行打印
void printCharArrayToHex(char *buf, int bytes) {
int i;
for (i = 0; i < bytes; i++)
{
printf("%x ", (unsigned char)buf[i]);
}
}
c#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
// 创建一个简单UDP服务器 监听1324端口
int main(int argc, char const *argv[])
{
printf("start monitor on 192.168.189.17:1324 \n");
// 创建套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // SOCK_DGRAM是UDP套接字
// sockfd这个名字中的fd 是文件描述符的缩写 在unix/linux中 fd是进程独有的文件描述符表的索引 它的意思是 socket可以被视作一个文件
if (sockfd == -1) {
perror("create socket failed: \n");
return -1;
}
// 设置服务器地址
struct sockaddr_in addr;
addr.sin_family = AF_INET; // 地址族
addr.sin_port = htons(1324); // 端口
addr.sin_addr.s_addr = inet_addr("192.168.189.17"); // IP 另外 INADDR_ANY可表示0.0.0.0
// 将套接字绑定到服务器地址上
int ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)); // addr这里 可以视作做了一个转型
if (0 > ret) {
// 绑定失败
perror("bind failed: \n");
close(sockfd);
return -1;
}
// 设置客户端地址
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
char buffer[1024];
while (1)
{
ssize_t bytes_recv = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&client_addr, &client_len);
if (bytes_recv == -1) {
perror("receive message error: \n");
continue;
}
char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, INET_ADDRSTRLEN);
int clinet_port = ntohs(client_addr.sin_port);
printf("client ip: %s, port: %d\n", client_ip, clinet_port);
printf("received from client: %s\n", buffer);
memset(buffer, 0, sizeof(buffer));
// 按老师要求 编写自定义回复内容
const char* response = "Hello from server! \0";
// 定义char数组
char buf[1024];
// 声明一个指针 并且指向buf数组的第一个元素
u_int8_t *p;
p = buf;
// 填充24进去
buf[0] = 24;
// 指针转型 使得编辑的内容从一位变成了两位 另外多字节内容必须转换字节序
*((u_int16_t*)(buf + 1)) = htons(2024);
// 同上的指针转型
*((u_int32_t*)(buf + 3)) = htonl(20240304);
// 获取主机名 如果无法获取则填充"Unknown Host"
if (gethostname(buf + 7, 1017) == -1) {
strcpy(buf + 7, "Unknown Host");
}
ssize_t bytes_send = sendto(sockfd, buf, 1017, 0, (struct sockaddr*)&client_addr, client_len);
if (bytes_send == -1) {
perror("sending message error: \n");
}
}
close(sockfd);
return 0;
}
可见局域网内的两个IP成功地进行通信,并且通信内容中包含主机名。
局域网内的两个主机通过这种方式通信,必须关闭双方主机的防火墙:
如果WSL想要被外界以一个固定IP访问,那么必须修改用户文件夹下的.wslconfig
文件,并且修改hostAddressLoopback
参数为true
。
在这里附上微软官方的说明:
(请注意,该说明为2024年3月5日截取,实际微软可能修改,请以最新说明为准WSL中的高级设置配置 | Microsoft Learn)
实际效果:
本文作者:御坂19327号
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!