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; }