4 TCP通信code
字节序、ip地址和整数转换、tcp/ip通信
0706笔记就记了,但是具体是哪个函数遗忘了,赶紧来复习下
重点:0916面试问道了,ip地址和整数怎么转换
/*
#include <arpa/inet.h>
// p:点分十进制的IP字符串,n:表示network,网络字节序的整数
int inet_pton(int af, const char *src, void *dst);
af:地址族: AF_INET AF_INET6
src:需要转换的点分十进制的IP字符串
dst:转换后的结果保存在这个里面
// 将网络字节序的整数,转换成点分十进制的IP地址字符串
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
af:地址族: AF_INET AF_INET6
src: 要转换的ip的整数的地址
dst: 转换成IP地址字符串保存的地方
size:第三个参数的大小(数组的大小)
返回值:返回转换后的数据的地址(字符串),和 dst 是一样的
*/
- 字节序
byteorder.c文件 判断当前机器的字节序 |
/* 字节序:字节在内存中存储的顺序。 小端字节序:数据的高位字节存储在内存的高位地址,低位字节存储在内存的低位地址 大端字节序:数据的低位字节存储在内存的高位地址,高位字节存储在内存的低位地址 */
// 通过代码检测当前主机的字节序 #include <stdio.h>
int main() { union { short value; // 2字节 char bytes[sizeof(short)]; // char[2] } test;
test.value = 0x0102; if((test.bytes[0] == 1) && (test.bytes[1] == 2)) { printf("大端字节序\n"); } else if((test.bytes[0] == 2) && (test.bytes[1] == 1)) { printf("小端字节序\n"); } else { printf("未知\n"); }
return 0; } |
bytrtrans.c文件 字节序转换 |
/* 网络通信时,需要将主机字节序转换成网络字节序(大端), 另外一段获取到数据以后根据情况将网络字节序转换成主机字节序。
// 转换端口 uint16_t htons(uint16_t hostshort); // 主机字节序 - 网络字节序 uint16_t ntohs(uint16_t netshort); // 主机字节序 - 网络字节序
// 转IP uint32_t htonl(uint32_t hostlong); // 主机字节序 - 网络字节序 uint32_t ntohl(uint32_t netlong); // 主机字节序 - 网络字节序 */
#include <stdio.h> #include <arpa/inet.h>
int main() { // htons 转换端口 unsigned short a = 0x0102; printf("a : %x\n", a); unsigned short b = htons(a); printf("b : %x\n", b);
printf("=======================\n");
// htonl 转换IP char buf[4] = {192, 168, 1, 100}; int num = *(int *)buf; int sum = htonl(num); unsigned char *p = (char *)∑
printf("%d %d %d %d\n", *p, *(p+1), *(p+2), *(p+3));
printf("=======================\n");
// ntohl unsigned char buf1[4] = {1, 1, 168, 192}; int num1 = *(int *)buf1; int sum1 = ntohl(num1); unsigned char *p1 = (unsigned char *)&sum1; printf("%d %d %d %d\n", *p1, *(p1+1), *(p1+2), *(p1+3));
// ntohs
return 0; } |
- ip地址和整数转换
iptrans.c文件
|
/* #include <arpa/inet.h> // p:点分十进制的IP字符串,n:表示network,网络字节序的整数 int inet_pton(int af, const char *src, void *dst); af:地址族: AF_INET AF_INET6 src:需要转换的点分十进制的IP字符串 dst:转换后的结果保存在这个里面
// 将网络字节序的整数,转换成点分十进制的IP地址字符串 const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); af:地址族: AF_INET AF_INET6 src: 要转换的ip的整数的地址 dst: 转换成IP地址字符串保存的地方 size:第三个参数的大小(数组的大小) 返回值:返回转换后的数据的地址(字符串),和 dst 是一样的
*/ #include <stdio.h> #include <arpa/inet.h>
int main() { // 创建一个ip字符串,点分十进制的IP地址字符串 char buf[] = "192.168.1.4"; unsigned int num = 0;
// 将点分十进制的IP字符串转换成网络字节序的整数 inet_pton(AF_INET, buf, &num); unsigned char * p = (unsigned char *)# printf("%d %d %d %d\n", *p, *(p+1), *(p+2), *(p+3));
// 将网络字节序的IP整数转换成点分十进制的IP字符串 char ip[16] = ""; const char * str = inet_ntop(AF_INET, &num, ip, 16); printf("str : %s\n", str); printf("ip : %s\n", str); printf("%d\n", ip == str);
return 0; } |
- 代码实现tcp/ip通信
sever.c文件 服务端 |
// TCP 通信的服务器端
#include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h>
int main() {
// 1.创建socket(用于监听的套接字) int lfd = socket(AF_INET, SOCK_STREAM, 0);
if(lfd == -1) { perror("socket"); exit(-1); }
// 2.绑定 struct sockaddr_in saddr; saddr.sin_family = AF_INET; // inet_pton(AF_INET, "192.168.193.128", saddr.sin_addr.s_addr); saddr.sin_addr.s_addr = INADDR_ANY; // 0.0.0.0 saddr.sin_port = htons(9999); int ret = bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));
if(ret == -1) { perror("bind"); exit(-1); }
// 3.监听 ret = listen(lfd, 8); if(ret == -1) { perror("listen"); exit(-1); }
// 4.接收客户端连接 struct sockaddr_in clientaddr; int len = sizeof(clientaddr); int cfd = accept(lfd, (struct sockaddr *)&clientaddr, &len);
if(cfd == -1) { perror("accept"); exit(-1); }
// 输出客户端的信息 char clientIP[16]; inet_ntop(AF_INET, &clientaddr.sin_addr.s_addr, clientIP, sizeof(clientIP)); unsigned short clientPort = ntohs(clientaddr.sin_port); printf("client ip is %s, port is %d\n", clientIP, clientPort);
// 5.通信 char recvBuf[1024] = {0}; while(1) {
// 获取客户端的数据 int num = read(cfd, recvBuf, sizeof(recvBuf)); if(num == -1) { perror("read"); exit(-1); } else if(num > 0) { printf("recv client data : %s\n", recvBuf); } else if(num == 0) { // 表示客户端断开连接 printf("clinet closed..."); break; }
char * data = "hello,i am server"; // 给客户端发送数据 write(cfd, data, strlen(data)); }
// 关闭文件描述符 close(cfd); close(lfd);
return 0; } |
client.c文件 客户端 |
// TCP通信的客户端
#include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h>
int main() {
// 1.创建套接字 int fd = socket(AF_INET, SOCK_STREAM, 0); if(fd == -1) { perror("socket"); exit(-1); }
// 2.连接服务器端 struct sockaddr_in serveraddr; serveraddr.sin_family = AF_INET; inet_pton(AF_INET, "192.168.193.128", &serveraddr.sin_addr.s_addr); serveraddr.sin_port = htons(9999); int ret = connect(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if(ret == -1) { perror("connect"); exit(-1); }
// 3. 通信 char recvBuf[1024] = {0}; while(1) {
char * data = "hello,i am client"; // 给客户端发送数据 write(fd, data , strlen(data));
sleep(1);
int len = read(fd, recvBuf, sizeof(recvBuf)); if(len == -1) { perror("read"); exit(-1); } else if(len > 0) { printf("recv server data : %s\n", recvBuf); } else if(len == 0) { // 表示服务器端断开连接 printf("server closed..."); break; }
}
// 关闭连接 close(fd);
return 0; } |