一、IPv4地址族和字符地址间的转换
1、inet_pton
int inet_pton(int af, const char *src, void *dst);
功能://把字符串IP转为数字IP
参数1:AF_INET ipv4地址族; AF_INE6 ipv6 地址族
参数2:字符串IP地址
参数3:网络二进制IP地址
u_int32_t ip ;
//把字符串IP转为数字IP
inet_pton(AF_INET,"192.168.100.1",&ip);
// printf("%u\n",ip);
2、inet_ntop
const char *inet_ntop(int af, const vo
char buf[128];
inet_ntop(AF_INET,&ip,buf,sizeof(buf));
printf("%s\n",buf);
id *src, char *dst, socklen_t size);
功能://把数字IP转为字符串IP
参数1:AF_INET ipv4地址族; AF_INE6 ipv6 地址族
参数2:网络二进制IP地址
参数3:字符串IP地址
参数4:指向缓存区dst的大小,避免溢出
二、地址族结构
1、通用地址族结构
struct sockaddr {
sa_family_t sa_family; /* 地址族 */
char sa_data[14]; /* 地址值,实际可能更长 */
};
2、IPV4地址族结构
struct in_addr {
in_addr_t s_addr;
};
struct sockaddr_in {
uint16_t sin_family;
uint16_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
3、案例
u_int32_t ip;
inet_pton(AF_INET, "192.168.40.148", &ip);
struct sockaddr_in addr;
addr.sin_addr.s_addr = ip;
addr.sin_family = AF_INET;
addr.sin_port = htons(6666);
使用该结构体的时候,要把结构体转换为通用地址族结构体,比如(struct sockaddr *)&addr
三、TCP连接(详细步骤)
(一)、服务器
1、SOCKET
是一种通信机制,可以使用TCP和UDP协议,亦可以自定义协议。
int listenSD= socket(AF_INET,SOCK_STREAM,0);
作用:创建并返回SOCKET的ID
参数1:协议族
参数2:具体使用的哪种通信协议TCP/UDP
参数3:一般为0即可
2、绑定网络地址
//把地址和socket绑定,避免地址被别人占用,客户单也会到这里来联系我们
bind(listenSD,(struct sockaddr*)&addr,sizeof(addr));
//参数1:socket的ID
//参数2:要绑定的地址
//参数3:地址结构体的长度
3.监听网络连接
listen(listenSD,5);
作用:监听客户端的链接
参数1:是在哪个socket上监听
参数2:在繁忙的时候,允许同时有几个客户端排队链接,而不是直接拒绝他们
4、接受客户端链接
//用来存放来访者的地址的结构体
struct sockaddr_in clientAddr;
//用来存放客户端地址结构体的长度
socklen_t clientAddrLen = sizeof(clientAddr);
//接受客户端端的链接,并且产生和返回与客户端通信的套接字ID,如果没有客户端连接,
//那么该函数会阻塞等待
int clientSD = accept(listenSD,(struct sockaddr*)&clientAddr,&clientAddrLen);
参数1:用来接听客户端链接的套接字ID
参数2:保存客户端地址的截割头
参数3:客户端地址结构体的长度
(二)、客户端
客户端要做的事情就是连接服务器
connect(sd,(struct sockaddr*)&addr,sizeof(addr));
作用:连接指定的地址
参数1:用来连接的套接字ID
参数2:要连接的地址结构体
参数3:地址结构体的长度
(三)、案例
1、服务器
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
int main()
{
u_int32_t ip ;
//把字符串IP转为数字IP,127.0.0.1代表本机地址
inet_pton(AF_INET,"192.168.40.111",&ip);
//网络地址结构体
struct sockaddr_in addr;
addr.sin_family = AF_INET;//IPV4的地址族
addr.sin_addr.s_addr = ip;//IP地址f
addr.sin_port = htons(9000);//端口
//创建socket,专门用来接受客户端链接的,它不会与客户端聊天通信
int listenSD = socket(AF_INET,SOCK_STREAM,0);
//把地址和socket绑定,避免地址被别人占用,客户单也会到这里来联系我们
bind(listenSD,(struct sockaddr*)&addr,sizeof(addr));
//监听是否有客户端链接
listen(listenSD,5);
//用来存放来访者的地址的结构体
struct sockaddr_in clientAddr;
//用来存放客户端地址结构体的长度
socklen_t clientAddrLen = sizeof(clientAddr);
//接受客户端端的链接,并且产生和返回与客户端通信的套接字ID
int clientSD = accept(listenSD,(struct sockaddr*)&clientAddr,&clientAddrLen);
char buf[512];
//从和客户端连接的套接字上读取客户端发来的消息
read(clientSD,buf,sizeof(buf));
printf("%s\n",buf);
close(clientSD);
close(listenSD);
// char buf[128];
// inet_ntop(AF_INET,&ip,buf,sizeof(buf));
// printf("%s\n",buf);
return 0;
}
2、客户端
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
int main()
{
u_int32_t ip ;
//把字符串IP转为数字IP
inet_pton(AF_INET,"192.168.40.111",&ip);
//服务器的地址结构体
struct sockaddr_in addr;
addr.sin_family = AF_INET;//IPV4的地址族
addr.sin_addr.s_addr = ip;//IP地址f
addr.sin_port = htons(9000);//端口
//创建socket,用来连接服务器,并且负责和服务器通信
int sd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == connect(sd,(struct sockaddr*)&addr,sizeof(addr)))
{
perror("");
}
char buf[512] = "hello world!";
write(sd,buf,sizeof(buf));
close(sd);
// char buf[128];
// inet_ntop(AF_INET,&ip,buf,sizeof(buf));
// printf("%s\n",buf);
return 0;
}
四、总结
此文章是学习一个简易的TCP连接的笔记。