😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍网络编程入门知识:TCP协议、TCP客户端、TCP服务端 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
本文未经允许,不得转发!!!
目录
- 🎄一、TCP协议概述
- 🎄二、一个最简单的TCP客户端
- ✨2.1 tcp客户端步骤和代码
- ✨2.2 tcp客户端相关函数
- 🎄三、一个最简单的TCP服务端
- ✨2.1 tcp服务端步骤和代码
- ✨2.2 tcp服务端相关函数
- 🎄四、总结
🎄一、TCP协议概述
TCP协议的全称是传输控制协议
(Transmission Control Protocol)。TCP是一个面向连接的协议,为用户进程提供可靠的全双工字节流。TCP套接字是一种流套接字( streamsocket)。TCP关心确认、超时和重传之类的细节。大多数因特网应用程序使用TCP。注意,TCP既可以使用IPv4,也可以使用IPv6。
TCP协议的几个特点:
- 1、TCP是通过连接(connection)来通信的。TCP客户端与某个TCP服务端建立连接,然后通过这个连接与服务端交互数据,最后终止这个连接。
- 2、TCP是可靠性(reliability)。当TCP向另一端发送数据时,它要求对端返回一个确认。如果没有收到确认,TCP就自动重传数据并等待更长时间。在数次重传失败后,TCP才放弃,如此在尝试发送数据上所花的总时间一般为4~10分钟(依赖于具体实现)。
TCP会给每个分节关联一个序列号,如果接收到重复数据,可以判定数据重复并丢弃。 - 3、TCP提供流量控制(flow control)。TCP总是会告诉对端,它一次能够从对端接收多少个字节的数据,这成为通告窗口(advertised window)。该窗口指出接收缓冲区的当前可用字节。
- 4、TCP是全双工的(full-duplex)。表示在同一个TCP连接上,同一时刻可以同时发送、接收数据。
🎄二、一个最简单的TCP客户端
✨2.1 tcp客户端步骤和代码
编写TCP客户端的步骤:
- 1、创建TCP套接字
socket
;- 2、指定TCP服务端ip和端口,bzero、inet_pton
- 3、建立与TCP服务端的连接,
connect
- 4、交互数据
- 5、关闭套接字
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main()
{
// 1、创建TCP套接字socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd<0)
perror("socket error" );
// 2、准备服务端ip和端口
struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons (10086);
if (inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr) <= 0) // 设置本机IP为服务端IP
perror("inet_pton error");
// 3、连接 connect
if (connect(sockfd,(struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
perror("connect error" );
// 4、交换数据
printf("TcpCli sockfd=%d, send msg\n",sockfd);
write(sockfd, "Hello,I am tcp client", strlen("Hello,I am tcp client"));
char recvline[256];
int n = 0;
while ( (n = read (sockfd, recvline, sizeof(recvline))) > 0)
{
recvline[n] = 0 ;/*null terminate */
printf("recv[%s]\n",recvline);
}
if (n < 0)
perror("read error" );
// 5、关闭
close(sockfd);
return 0;
}
✨2.2 tcp客户端相关函数
-
socket 函数
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol);
socket函数创建一个套接字描述符。man手册描述,socket创建一个通信端点并返回一个描述符。
- 参数
domain
指定通信域,使用了AF_INET
,表示是IPv4 Internet protocols
协议的。 - 参数
type
指定套接字类型,使用``,表示TCP协议的套接字(提供有序、可靠、双向、基于连接的字节流。可以支持带外数据传输机制)。 - 参数
protocol
指定了要与套接字一起使用的特定协议。通常,在给定的协议族中,只有一个协议支持特定的套接字类型,在这种情况下,协议可以指定为0。
- 参数
-
connect 函数
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
connect 函数将文件描述符
sockfd
引用的套接字连接到addr
指定的地址。addrlen
参数指定addr的大小。addr中地址的格式由套接字sockfd的地址空间决定;
🎄三、一个最简单的TCP服务端
✨2.1 tcp服务端步骤和代码
编写TCP服务端的步骤:
- 1、创建TCP套接字
socket
;- 2、准备服务端ip和端口;
- 3、绑定,
bind
- 4、监听,
listen
- 5、接受客户端连接,
accept
- 6、与客户端进行数据交互
- 7、关闭套接字
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main()
{
// 1、创建TCP套接字socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd<0)
perror("socket error" );
// 2、准备服务端ip和端口
struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons (10086);
servaddr.sin_addr.s_addr = INADDR_ANY; // 指定ip地址为 INADDR_ANY,这样要是服务器主机有多个网络接口,服务器进程就可以在任一网络接口上接受客户端的连接
// 3、绑定 bind
if (bind(sockfd,(struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
perror("bind error" );
// 4、监听 listen
if(listen(sockfd, 10) != 0)
perror("listen error");
printf("TcpSer sockfd=%d, start listening\n",sockfd);
char recvline[256];
while(1)
{
// 5、接受客户端连接
int connfd = accept(sockfd, NULL, NULL);
// 6、与客户端交换数据
int n = read(connfd, recvline, sizeof(recvline));
if(n>0)
{
recvline[n] = 0 ;/*null terminate */
printf("recv connfd=%d [%s]\n",connfd,recvline);
}
write(connfd, "Hello,I am tcp server", strlen("Hello,I am tcp server"));
close(connfd);
}
// 7、关闭
close(sockfd);
return 0;
}
socket
、bind
和listen
这3个调用步骤是任何TCP服务器准备所谓的监听描述符(listening descriptor)的正常步骤。
✨2.2 tcp服务端相关函数
tcp服务端相关函数有:socket、bind、listen、accept。socket函数可以参照上面 2.2 小节。
- bind 函数
bind函数将addr指定的地址分配给文件描述符sockfd引用的套接字。addrlen指定addr指向的地址结构的大小。#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- listen 函数
listen函数将sockfd引用的套接字标记为#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int listen(int sockfd, int backlog);
被动套接字
,标记后,可以使用accept
函数接受传入连接请求的套接字。- backlog参数定义了sockfd的挂起连接队列可能增长到的最大长度。如果连接请求在队列已满时到达,则客户端可能会接收到带有ECONNREFUSED指示的错误,或者,如果底层协议支持重传,则可以忽略该请求,以便稍后重新尝试连接成功。
- accept 函数
accept函数用于基于连接的套接字类型(SOCK_STREAM、SOCK_SEQPACKET)。它提取侦听套接字的挂起连接队列中的第一个连接请求sockfd,创建一个新的连接套接字,并返回一个引用该套接字的新文件描述符。新创建的套接字未处于侦听状态。原始套接字sockfd不受此调用的影响。#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
🎄四、总结
👉本文主要介绍Linux下网络编程的基础知识,先是简单介绍一下TCP协议,然后给出一个TCP客户端、TCP服务端最简单的例子,最后介绍创建TCP客户端、TCP服务端需要用到的函数。
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁