1.概念
1.1TCP
概念:
TCP(Transmission Control Protocol)协议指的是传输控制协议,是一个面向连接的传输协议,他是一个能提供高可靠性的通信协议,所谓高可靠性指的是数据无丢失、数据无误、数据无失序、数据无重到达。(打电话)
适用场景:
- 适用于对传输质量要求较高,以及传输大量数据的通信。
- 在需要传输可靠数据的场合通常会选择使用TCP通信协议。
- 比如QQ/微信/支付宝等通信软件的账户登录和支付相关功能是通常采用可靠的TCP通信协议来实现。
1.2UDP
概念:
UDP(User Datagram Protocol)指的是用户数据报协议,是一种不可靠无连接的协议,在数据发送前,不需要提前建立连接,所以可以更高效地传输数据。(发邮件)
适用场景:
- 发送小尺寸地数据(例如对DNS服务器进行地址查询或路游器更新路由表)
- 在收到数据,给出应答比较困难地网络中适用UDP(比如无线网络)
- 适用于广播/组播式通信。
- QQ/微信等即时通信软件地点对点文件通讯以及音视频通话时。
- 流媒体、VoIOP、IPTV等网络多媒体服务中(直播间)
2.API接口:
2.1TCP 实现通信
2.1.1服务器端:
1.创建TCP套接字
//int socket(int domain, int type, int protocol);
// 创建一个TCP套接字并返回描述符
int sock_fd socket(AF_INET, SOCK_STREAM , 0 );
if (-1 == sock_fd)
{
perror("socket error");
return -1;
}
2.绑定IP地址到和端口号
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//配置端口号和IP信息
struct sockaddr_in my_addr;
int addr_len = sizeof(my_addr); // 计算地址结构体大小
my_addr.sin_family = AF_INET ; // 选择为IPV4地址
my_addr.sin_port = htons(65000); // 配置端口号, 注意转为网络字节序
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 设置IP地址并转为网络字节序
// 绑定地址和端口等信息与套接字
int ret_val = bind(sock_fd , (struct sockaddr *)&my_addr, addr_len);
if (-1 == ret_val)
{
perror("绑定失败");
return -1;
}
3.把套接字设置为监听状态
// 把配置好的套接字设置为监听状态
ret_val = listen( sock_fd , 5);
if (-1 == ret_val)
{
perror("设置监听失败");
return -1 ;
}
4.等待客户端连接
// 等待客户端连接
struct sockaddr_in other_addr;
int connect_fd accept(sock_fd , (struct sockaddr *)&other_addr, &addr_len);
if (connect_fd == -1)
{
perror("连接失败");
return -1 ;
}
5.接收客户端来消息
// 等待客户端发话
char * msg = calloc(1, 1024);
ret_val = recv(sock_fd , msg , 1024 , 0);
if (-1 == ret_val)
{
perror("接收失败");
return -1 ;
}
else
{
printf("鱼头怪老大说:%s\n" , msg);
}
6.挂断电话
close(sock_fd);
2.2.2客户端:
1.创建套接字
// 创建一个TCP套接字并返回描述符
int sock_fd = socket(AF_INET, SOCK_STREAM , 0 );
if (-1 == sock_fd)
{
perror("socket error");
return -1;
}
2.连接服务器
//配置端口号和IP信息
struct sockaddr_in serve_addr;
int addr_len = sizeof(serve_addr); // 计算地址结构体大小
serve_addr.sin_family = AF_INET ; // 选择为IPV4地址
serve_addr.sin_port = htons(65000); // 配置端口号, 注意转为网络字节序
serve_addr.sin_addr.s_addr = inet_addr("172.17.194.54"); // 设置IP地址并转为网络字节序
//发起连接请求
int ret_val = connect(sock_fd , (struct sockaddr *)&serve_addr, addr_len );
if (ret_val == -1 )
{
perror("发起连接失败");
return -1 ;
}
printf("连接成功!!!\n" );
3.发送消息
// 获取输入并发送
char * msg = calloc(1, 1024);
fgets(msg , 1024 , stdin );
ret_val = send(sock_fd , msg , strlen(msg), 0 );
if (-1 == ret_val)
{
perror("发送失败");
return -1 ;
}
else
{
printf("发送成功:%s\n" , msg);
}
4.挂断电话
close(sock_fd);
2.2UDP 实现通信
2.2.1服务端
1. 创建信箱
//创建信箱
int sock_fd = socket(AF_INET, SOCK_DGRAM , 0);
if (-1 == sock_fd)
{
perror("socket failed");
return -1 ;
}
2. 设置信箱地址和端口号
//设置信箱地址
/* struct sockaddr_in
{
u_short sin_family; // 地址族
u_short sin_port; // 端口
struct in_addr sin_addr; // IPV4 地址
char sin_zero[8];
};
*/
struct sockaddr_in addr;
int addrlen = sizeof(struct sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(65000);
addr.sin_addr.s_addr = inet_addr("172.17.194.54");
//帮定地址
int ret = bind(sock_fd, (struct sockaddr *)&addr, addrlen);
if ( -1 == ret )
{
printf("bind failed !!\n");
}else{
printf("bind succees !!\n");
}
3. 等待客户端来信
//等待来信
struct sockaddr_in addr_from;
char buf[100];
while(1)
{
bzero(buf,100);
ret = recvfrom( sock_fd, buf, 100 , 0 ,
(struct sockaddr *)&addr_from, &addrlen);
printf("msg: %s port: %d\naddr: %s\n",
buf,ntohs(addr_from.sin_port),
inet_ntoa(addr_from.sin_addr));
}
4. 关闭信箱
close(sock_fd);
2.2.2客户端:
1. 创建信箱
//创建信箱
int sock_fd = socket(AF_INET, SOCK_DGRAM , 0);
if (-1 == sock_fd)
{
perror("socket failed");
return -1 ;
}
2. 先设置好信件发送的地址
//设置信箱地址
/* struct sockaddr_in
{
u_short sin_family; // 地址族
u_short sin_port; // 端口
struct in_addr sin_addr; // IPV4 地址
char sin_zero[8];
};
*/
struct sockaddr_in addr;
int addrlen = sizeof(struct sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(65000);
addr.sin_addr.s_addr = inet_addr("172.17.194.54");
3. 写信并发送
//写信
int ret ;
char buf[100];
while(1)
{
bzero(buf,100);
fgets(buf,100 , stdin);
ret = sendto( sock_fd, buf, strlen(buf) , 0 , (struct sockaddr *)&addr, addrlen);
if ( -1 == ret )
{
perror("sendto failed ");
}else{
printf("sendto succeed !! \n");
}
}
4. 关闭信箱
close(sock_fd);