TCP简单链接的编程实现
本文主要介绍TCP应用层的编码实现。
TCP是一种面向连接的、可靠的、基于字节流的传输层协议,它是互联网协议套件(TCP/IP)中的核心协议之一,广泛应用于需要可靠数据传输的场景,如:网页浏览、文件传输、电子邮件等。
TCP简单链接的编程实现
- TCP简单链接的编程实现
- 编码实现
- 实现tcp编程之前需要明确的数据条件
- 相关函数介绍
-
- [`int socket(int domain,int type, int protocol);`](#
int socket(int domain,int type, int protocol);
)
- [`int socket(int domain,int type, int protocol);`](#
编码实现
tcp简单服务器实现
c
//头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080 //端口号
#define BUFFER_SIZE 1024 //接收buffer的缓存区大小
int main() {
int server_fd;//绑定的套接字
int new_socket; //建立的tcp连接
struct sockaddr_in server_address; //服务地址
int addrlen = sizeof(server_address);
struct sockaddr_in address; //建立连接时获取到的客户端地址
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0}; //接受缓冲区
char *response = "Hello from server"; //发送数据
// 1.创建套接字
/*
AF_INET:域: IPV4:AF_INET; IPV6: AF_INET6 本地通信:AF_UNIX或AF_LOCAL 底层数据包接口(用于直接访问网络层数据包): AF_PACKET
SOCK_STREAM:类型,TCP填SOCK_STREAM;UDP填SOCK_DGRAM;原始套接字填SOCK_RAW
0:协议,一般填0(根据 domain 和 type 自动选择合适的协议),原始套接字编程时需填充
返回值:成功时:返回一个非负整数,表示套接字的文件描述符;失败时:返回 -1,并设置 errno 以指示错误类型。
*/
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}
//2.地址快速重用
/*
server_fd:套接字描述符
SOL_SOCKET:表示选项的级别
optname:表示要设置选项的名称
&flag:指向设置值的指针
len:设置值的大小
返回值:成功返回0,失败返回-1,并设置 errno 以指示错误类型
*/
int flag=1;
int len=sizeof(int);
if(setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&flag,len)!=0){
perror(("setsockopt SO_REUSEADDR failed"));
exit(EXIT_FAILURE);
}
//2.绑定套接字到端口 (设置域,ip,端口)
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY 的值是 0x00000000,表示 0.0.0.0,这是一个特殊的 IPv4 地址。
//当将套接字绑定到 INADDR_ANY 时,服务器会监听所有本地网络接口(包括环回接口 127.0.0.1 和所有物理网卡的 IP 地址)
address.sin_port = htons(PORT);
//3.绑定
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
close(server_fd);
exit(EXIT_FAILURE);
}
// 4.监听连接
if (listen(server_fd, 3) < 0) { //3:backlog正在三次握手的客户端链表的上限=2*backlog+1
perror("Listen failed");
close(server_fd);
exit(EXIT_FAILURE);
}
printf("Server listening on port %d\n", PORT);
// 5.接受连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("Accept failed");
close(server_fd);
exit(EXIT_FAILURE);
}
// 读取客户端发送的数据
read(new_socket, buffer, BUFFER_SIZE);
printf("Message from client: %s\n", buffer);
// 发送响应给客户端
send(new_socket, response, strlen(response), 0);
printf("Response sent to client\n");
// 关闭套接字
close(new_socket);
close(server_fd);
return 0;
}
tcp简单客户端实现
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sock = 0;
struct sockaddr_in serv_addr;
char *message = "Hello from client";
char buffer[BUFFER_SIZE] = {0};
// 创建套接字
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket creation error");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// 将IPv4地址从字符串转换为二进制形式
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
perror("Invalid address/ Address not supported");
return -1;
}
// 连接到服务器
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("Connection Failed");
return -1;
}
// 发送消息给服务器
send(sock, message, strlen(message), 0);
printf("Message sent to server\n");
// 读取服务器的响应
read(sock, buffer, BUFFER_SIZE);
printf("Response from server: %s\n", buffer);
// 关闭套接字
close(sock);
return 0;
}
实现tcp编程之前需要明确的数据条件
tcp服务端
(1)发送端口号
(2)接受数据的缓冲区
(3)发送端ip地址
(4)要发送的数据
(5)要设置三次握手的客户端链表的上限值
TCP客户端
(1)接收端口号
(2)接受数据的缓冲区
(3)接收端ip地址
(4)要发送的数据
相关函数介绍
int socket(int domain,int type, int protocol);
socket 函数是网络编程中用于创建套接字的核心函数。它定义在 <sys/socket.h> 头文件中,用于创建一个通信端点(套接字),并返回一个文件描述符,以便后续的通信操作(如绑定、监听、连接、发送和接收数据等)。
参数说明
domain(协议族/地址族)
指定通信的协议族,常见的值包括:
- AF_INET:IPv4 协议族(用于 TCP/IPv4 和 UDP/IPv4)。
- AF_INET6:IPv6 协议族(用于TCP/IPv6 和 UDP/IPv6)。
- AF_UNIX 或 AF_LOCAL:本地通信(用于同一台机器上的进程间通信)。
- AF_PACKET:底层数据包接口(用于直接访问网络层数据包)。
type(套接字类型)
指定套接字的类型
SOCK_STREAM:面向连接的流套接字(如 TCP)。
SOCK_DGRAM:无连接的数据报套接字(如 UDP)。
SOCK_RAW:原始套接字(用于直接访问网络层协议,如 ICMP)。
protocol(协议)
指定具体的协议,通常设置为 0,表示根据 domain 和 type 自动选择合适的协议。
- 如果 domain 是 AF_INET 且 type 是 SOCK_STREAM,则默认使用 IPPROTO_TCP(TCP 协议)。
- 如果 domain 是 AF_INET 且 type 是 SOCK_DGRAM,则默认使用 IPPROTO_UDP(UDP 协议)。
- 如果使用原始套接字(SOCK_RAW),则需要显式指定协议,如 IPPROTO_ICMP。
返回值
- 成功时:返回一个非负整数,表示套接字的文件描述符。
- 失败时:返回 -1,并设置 errno 以指示错误类型。