commit 6d6d3a393dbb00b6e6c55c25d237d3f66748b03c Author: flykhan Date: Tue Sep 5 20:54:17 2023 +0800 第2天上课 diff --git a/day2/n1.c b/day2/n1.c new file mode 100644 index 0000000..96a9851 --- /dev/null +++ b/day2/n1.c @@ -0,0 +1,23 @@ +#include + +union +{ + unsigned short num; + unsigned char c[2]; +} data; + +int main(int argc, char const *argv[]) +{ + data.num = 0x0102; + + if (data.c[0] == 1) + { + printf("大端字节序\n"); + } + else + { + printf("小端字节序\n"); + } + + return 0; +} diff --git a/day2/n2.c b/day2/n2.c new file mode 100644 index 0000000..f520079 --- /dev/null +++ b/day2/n2.c @@ -0,0 +1,13 @@ +#include +#include + +int main(int argc, char const *argv[]) +{ + unsigned int data=0x01020304; + // 转成网络端数据(小端转大端) + u_int32_t data2 = htonl(data); + printf("主机字节序: %#x\n",data); + printf("网络字节序: %#x\n",data2); + + return 0; +} diff --git a/day2/n3.c b/day2/n3.c new file mode 100644 index 0000000..fe5fdc9 --- /dev/null +++ b/day2/n3.c @@ -0,0 +1,17 @@ +#include +#include + +int main(int argc, char const *argv[]) +{ + unsigned int data = 0x01020304; + // 转成网络端数据(小端转大端) + uint32_t data2 = htonl(data); + printf("主机字节序: %#08x\n", data); + printf("网络字节序: %#x\n", data2); + + // 将网络字节序转为主机字节序 + uint32_t data3 = ntohl(data2); + printf("转换后主机字节序: %#x\n", data); + + return 0; +} diff --git a/day2/n4.c b/day2/n4.c new file mode 100644 index 0000000..5f74acf --- /dev/null +++ b/day2/n4.c @@ -0,0 +1,22 @@ +#include +#include + +int main(int argc, char const *argv[]) +{ + char *ip = "10.35.188.66"; + // ip 地址转换为四字节 + uint32_t ip_data; + + // 将 ip 转换为数值 + int ret = inet_pton(AF_INET, ip, &ip_data); + printf("ip转换数值的结果(%d): %#x\n", ret, ip_data); + + // 将 ip 的数值转换为 ipv6 字符串 + char ip_dst[25] = ""; + if (inet_ntop(AF_INET6, &ip_data, ip_dst, INET6_ADDRSTRLEN) != NULL) + { + printf("由数值转化为 ip 地址的字符串: %s\n", ip_dst); + } + + return 0; +} diff --git a/day2/n5.c b/day2/n5.c new file mode 100644 index 0000000..db0480b --- /dev/null +++ b/day2/n5.c @@ -0,0 +1,20 @@ +#include +#include +#include + +int main(int argc, char const *argv[]) +{ + + // 创建socket + int socket_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (socket_fd < 0) + { + perror("socket"); + return 1; + } + printf("socket 创建成功: %d\n", socket_fd); + + close(socket_fd); + + return 0; +} diff --git a/day2/n6_send.c b/day2/n6_send.c new file mode 100644 index 0000000..865889a --- /dev/null +++ b/day2/n6_send.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include // 地址结构 +#include +#include + +int main(int argc, char const *argv[]) +{ + // 1. 创建套接字 + int sfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sfd < 0) + { + perror("socket"); + return -1; + } + + // 2. 创建发送目标的ip地址和端口号 + struct sockaddr_in addr; + bzero(&addr, sizeof(addr)); // 初始化置零 + addr.sin_family = AF_INET; + addr.sin_port = htons(8000); + inet_pton(AF_INET, "10.35.188.66", &addr.sin_addr.s_addr); + + // 3. 创建发送的数据 + char *buf = "hi, udp server: disen hh"; + + // 4. 发送一次 udp 数据 + ssize_t n = sendto(sfd, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr)); + if (n > 0) + { + printf("发送 udp 数据成功\n"); + }else{ + printf("发送失败\n"); + perror("sendto"); + } + + // 5. 关闭 socket + close(sfd); + + return 0; +} diff --git a/day2/n6_send_2.c b/day2/n6_send_2.c new file mode 100644 index 0000000..3cc72b6 --- /dev/null +++ b/day2/n6_send_2.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include // 地址结构 +#include +#include + +int main(int argc, char const *argv[]) +{ + // 1. 创建套接字 + int sfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sfd < 0) + { + perror("socket"); + return -1; + } + + // 2. 创建发送目标的ip地址和端口号 + struct sockaddr_in addr; + bzero(&addr, sizeof(addr)); // 初始化置零 + addr.sin_family = AF_INET; + addr.sin_port = htons(8000); + inet_pton(AF_INET, "192.168.31.1", &addr.sin_addr.s_addr); + + int n = 1; + + // 3. 创建发送的数据 + while (1) + { + char buf[128] = ""; + scanf("%s", buf); + if (strncmp(buf, "exit", 4) == 0) + { + break; + } + // sprintf(buf, "this is : %lld\n", (n++ * ++n)); + + // 4. 发送一次 udp 数据 + ssize_t n = sendto(sfd, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr)); + if (n > 0) + { + printf("%s: 发送 udp 数据成功\n", buf); + } + else + { + printf("%s: 发送失败\n", buf); + perror("sendto"); + } + } + + // 5. 关闭 socket + close(sfd); + + return 0; +} diff --git a/day2/n7.c b/day2/n7.c new file mode 100644 index 0000000..7033f9c --- /dev/null +++ b/day2/n7.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) +{ + int sfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sfd < 0) + { + perror("socket"); + return -1; + } + + // 1. 绑定本地 ip 和端口号 + struct sockaddr_in addr; // sockaddr_in 结构体对象 + bzero(&addr, sizeof(addr)); + + addr.sin_family = AF_INET; + addr.sin_port = htons(8000); // 当前 Linux 进程的端口号 + addr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY 任意连接的 ip 可用 + // inet_pton(AF_INET, "192.168.31.128", &addr.sin_addr.s_addr); + + if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) // 绑定 + { + perror("bind"); + } + else + { + printf("bind success\n"); + + // 接收数据 + char buf[128] = ""; // 接收数据的空间 + struct sockaddr_in src_addr; // 数据来源的地址 + socklen_t addr_len; + while (1) + { + // 重置数据 + bzero(&src_addr, sizeof(src_addr)); + bzero(buf, 128); + + // 接收数据,如果数据未到达,则会阻塞,直到数据到达为止 + socklen_t addr_len = sizeof(src_addr); + ssize_t len = recvfrom(sfd, buf, 128, 0, (struct sockaddr *)&src_addr, &addr_len); + if (len < 0) + { + perror("recvfrom"); + break; + } + + char src_ip[16]; + int src_port = ntohs(src_addr.sin_port); // 将网络字节序转化为主机字节序 + inet_ntop(AF_INET, &src_addr.sin_addr.s_addr, src_ip, 16); // 从 src_addr 取 ip 并转化为字符串赋值给 src_ip + + printf("从 %s:%d 位置接受到的数据(%ld Bytes): %s\n", src_ip, src_port, len, buf); + + char buf2[1280]; + sprintf(buf2, "返回: %s\n", buf); + // 回一句消息 + sendto(sfd, buf2, strlen(buf2), 0, (struct sockaddr *)&src_addr, addr_len); + } + } + + close(sfd); + + return 0; +} diff --git a/day2/qq/qq.c b/day2/qq/qq.c new file mode 100644 index 0000000..8d662cb --- /dev/null +++ b/day2/qq/qq.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include +#include // atoi + +void *recv_task(void *arg); // 接收数据的线程任务函数 +void *send_task(void *arg); // 发送数据的线程任务函数 + +int main(int argc, char const *argv[]) +{ + if (argc != 2) + { + printf("usage: %s port\n", argv[0]); + return 1; + } + + int sfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sfd < 0) + { + perror("socket"); + return -1; + } + + // 绑定 ip 和端口号 (开启 UDP 服务) + struct sockaddr_in bind_addr; + bzero(&bind_addr, sizeof(bind_addr)); + bind_addr.sin_family = AF_INET; + bind_addr.sin_port = htons(atoi(argv[1])); + bind_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 主机 ip 中的任意一个都可以使用 + + if (bind(sfd, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) + { + perror("bind"); + close(sfd); + return -1; + } + + pthread_t t1, t2; + pthread_create(&t1, NULL, recv_task, (void *)&sfd); + pthread_create(&t2, NULL, send_task, &sfd); + + pthread_join(t2, NULL); + pthread_cancel(t1); // 发完后,取消接收 + pthread_join(t1, NULL); // 等待接收线程结束 + + close(sfd); + + return 0; +} + +void *recv_task(void *arg) +{ + int sock_fd = *((int *)arg); // 取出传入的 socket 描述符 + printf("启动recv_task %d\n", sock_fd); + char buf[128] = ""; + struct sockaddr_in src_addr; // 发送数据的源地址 + socklen_t sock_len; // 原地址 socket 的长度 + + while (1) + { + bzero(buf, sizeof(buf)); + bzero(&src_addr, sizeof(src_addr)); + + ssize_t len = recvfrom(sock_fd, buf, sizeof(buf), 0, (struct sockaddr *)&src_addr, &sock_len); + if (len < 0) + { + perror("recvfrom"); + } + + char ip[INET_ADDRSTRLEN] = ""; + int port = ntohs(src_addr.sin_port); + inet_ntop(AF_INET, &src_addr.sin_addr.s_addr, ip, INET_ADDRSTRLEN); + + printf("%s:%d 说: %s\n", ip, port, buf); + } +} + +void *send_task(void *arg) +{ + int sock_fd = *((int *)arg); + // @192.168.1.2:8000 + // hi,hello + // good,disen + // haha + // yes + // @:8500 + // very,good + + char ip[INET_ADDRSTRLEN] = ""; + int port = 0; + struct sockaddr_in dst_addr; // 目标地址 + while (1) + { + char buf[128] = ""; + fgets(buf, sizeof(buf), stdin); + buf[strlen(buf) - 1] = 0; // 去掉最后的换行 + + if (buf[0] == '@') + { + if (buf[1] == ':') + { + strcpy(ip, "127.0.0.1"); + port = atoi(buf + 2); + } + else + { + strcpy(ip, strtok(buf + 1, ":")); + port = atoi(strtok(NULL, ":")); + } + + printf("ip:port is %s:%d\n",ip,port); + // 重置 + bzero(&dst_addr, sizeof(dst_addr)); + dst_addr.sin_family = AF_INET; + dst_addr.sin_port = htons(port); + // inet_pton(AF_INET, ip, &dst_addr.sin_addr.s_addr); // 按ipv4转地址 + dst_addr.sin_addr.s_addr = inet_addr(ip); + // inet_pton(sock_fd, ip, &dst_addr.sin_addr.s_addr); // bug地方 + } + else + { + if (strncmp(buf, "exit", 4) == 0) + { + break; + } + + if (port == 0) + { + printf("请先确认发送的目的ip和端口号\n"); + continue; + } + + // 发送数据 + if (sendto(sock_fd, buf, strlen(buf), 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr)) < 0) + { + perror("sendto"); + } + } + } +} \ No newline at end of file diff --git a/day2/test2.c b/day2/test2.c new file mode 100644 index 0000000..2051932 --- /dev/null +++ b/day2/test2.c @@ -0,0 +1,33 @@ +#include +#include + +int main(int argc, char const *argv[]) +{ + unsigned int data = 0x01020304; + printf("主机字节序: "); + for (int i = 0; i < sizeof(unsigned int); i++) { + unsigned char byte = (data >> (i * 8)) & 0xFF; + printf("%02x", byte); + } + printf("\n"); + + // 转成网络字节序(小端转大端) + uint32_t data2 = htonl(data); + printf("网络字节序: "); + for (int i = 0; i < sizeof(uint32_t); i++) { + unsigned char byte = (data2 >> (i * 8)) & 0xFF; + printf("%02x", byte); + } + printf("\n"); + + // 将网络字节序转为主机字节序 + uint32_t data3 = ntohl(data2); + printf("转换后主机字节序: "); + for (int i = 0; i < sizeof(uint32_t); i++) { + unsigned char byte = (data3 >> (i * 8)) & 0xFF; + printf("%02x", byte); + } + printf("\n"); + + return 0; +}