TCP传输
TCP(Transmission Control Protocol)即传输控制协议,是一个工业标准的协议集,它是为广域网(WANs)设计的提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个 TCP 连接,之后才能传输数据。TCP 提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
TCP 的三次握手建立连接
TCP 的四次挥手断开连接
TCP传输过程
函数
socket()
domain(协议族):
type(类型):
protocol(协议):
通常赋为0
字节序转换
uint32_t htonl(uint32_t hostlong); //把32位值从主机字节序转换成网络字节序
uint16_t htons(uint16_t hostshort);//把16位值从主机字节序转换成网络字节序
uint32_t ntohl(uint32_t netlong); //把32位值从网络字节序转换成主机字节序
uint16_t ntohs(uint16_t netshort); //把32位值从网络字节序转换成主机字节序
in_addr_t inet_addr(const char *cp);//返回网络字节序
in_addr_t inet_network(const char *cp);//返回主机字节序
char *inet_ntoa(struct in_addr in);//网络字节 ——》IP字符串
int inet_aton(const char *cp, struct in_addr *inp);//返回网络字节序
bind()
sockfd:创建的套接字描述符
addr:服务器端的地址和端口
listen()
accept()
recv()
服务器示例
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sock_fd;
struct sockaddr_in ser_addr;
struct sockaddr_in cli_addr;
char buff[1024] = {0};
//调用socket函数创建监听套接字,协议族为AF_INET,socket类型为SOCK_STREAM流式套接字,协议为
//IPPROTO_TCP协议,也可以为0,默认
sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock_fd < 0){
perror("socket error!");
return -1;
}
//赋值监听地址信息
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(9000);
ser_addr.sin_addr.s_addr = inet_addr("192.168.121.128");
int len = sizeof(struct sockaddr_in);
int ret;
int client_fd;
//调用bind函数将套接字与地址信息进行绑定
ret = bind(sock_fd, (struct sockaddr*)&ser_addr, len);
if (ret < 0){
perror("bind error!!");
return -1;
}
//调用listen函数开始监听套接字(即开始监听地址,等待连接请求的到来)
ret = listen(sock_fd, 5);
if (ret < 0){
perror("listen error!!");
return -1;
}
while (1){
//调用accept函数接收到来的连接请求,并获取客户端的地址信息,返回一个传输socket套接字
client_fd = accept(sock_fd, (struct sockaddr*)&cli_addr, &len);
if (client_fd < 0){
perror("client_fd error!!");
continue;
}
printf("new client:-ip:[%s], port:[%d]\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
while (1){
memset(buff, 0x00, 1024);
//调用recv函数接收客户端传输过来的数据
ret = recv(client_fd, buff, 1024, 0);
printf("[%s]\n", buff);
sleep(1);
}
//调用close函数关闭套接字
close(client_fd);
}
close(sock_fd);
return 0;
}
客户端示例
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sock_fd;
struct sockaddr_in ser_addr;
struct sockaddr_in cli_addr;
char buff[1024] = {0};
//调用socket函数创建套接字
sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock_fd < 0){
perror("socket error!");
return -1;
}
//赋值发送地址信息,服务器端地址信息
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(9000);
ser_addr.sin_addr.s_addr = inet_addr("192.168.121.128");
cli_addr.sin_family = AF_INET;
cli_addr.sin_port = htons(8000);
cli_addr.sin_addr.s_addr = inet_addr("192.168.121.128");
int len = sizeof(struct sockaddr_in);
int ret;
//调用 bind 函数绑定一个发送地址信息
ret = bind(sock_fd, (struct sockaddr*)&cli_addr, len);
if (ret < 0){
perror("bind error!!!");
return -1;
}
//调用 connect 函数连接服务器
ret = connect(sock_fd, (struct sockaddr*)&ser_addr, len);
if (ret < 0){
perror("connect error!!!");
return -1;
}
int i = 0;
while (1){
memset(buff, 0x00, 1024);
sprintf(buff, "test-%d", i++);
//连接成功后,调用 send 函数发送数据到服务器端
send(sock_fd, buff, 1024, 0);
sleep(1);
}
//调用 close 函数关闭套接字
close(sock_fd);
return 0;
}