阵雨后放晴的天空中,
出现的彩虹很快便会消失。
而人心中的彩虹却永不会消失。
--- 太宰治 《斜阳》---
从零开始使用TCP进行socket编程
1 TCP与UDP
我们之前实现了UDP协议下的客户端与服务端的通信。
UDP(用户数据报协议)和TCP(传输控制协议)都是网络通信中常用的传输层协议,它们在数据传输的方式和特性上存在以下特点:
TCP
- TCP 是面向连接的协议,意味着在数据传输之前,必须先建立一个连接,完成握手过程。这个连接在数据传输结束之后需要被断开。
- TCP 提供了可靠的服务。它确保数据包的顺序传输,并且通过确认(ACK)和重传机制保证数据的可靠性。
- TCP 因为需要建立连接、保证数据顺序和可靠性,所以传输速度相对较慢。
- TCP 将数据视为一个连续的数据流,确保数据按照发送的顺序到达。
- TCP 适用于要求高可靠性的应用,如网页浏览、文件传输(FTP)、电子邮件(SMTP)等。
- TCP 头部较大,因为它需要包含更多的信息来管理连接状态和保证数据的可靠性。
UDP
- UDP 是无连接的,它发送数据之前不需要建立连接,每个数据报文都是一个独立的信息传输单位。
- UDP 不保证数据包的顺序,也不保证数据包的可靠性。如果数据在传输过程中丢失,UDP不会进行重传。
- UDP 由于无需建立连接和保证可靠性,通常用于对实时性要求较高的应用,如视频会议和在线游戏,传输速度较快。
- UDP 将数据视为独立的、离散的数据包(datagrams),每个数据包独立处理,可能以不同的顺序到达。
- UDP 头部较小,处理起来更为高效。
- UDP 适用于实时性要求高的应用,如流媒体、实时视频会议(VoIP)、在线游戏等。
通俗理解的话:TCP的传输过程类似管道,数据从一端发送,然后在另一端按顺序接收。UDP传输数据的过程类似送快递,数据报文会一股脑包装在一起发送给接收者!
2 TCP服务器类
2.1 TCP基础知识
• socket()打开一个网络通讯端口,如果成功的话,就像 open()一样返回一个文件描述符;
• 应用程序可以像读写文件一样用 read / write 在网络上收发数据,通过流来进行读取写入!
• 如果 socket()调用出错则返回-1;
• 对于 IPv4, family 参数指定为 AF_INET;
• 对于 TCP 协议,type 参数指定为 SOCK_STREAM, 表示面向流的传输协议
• protocol 参数的介绍从略,指定为 0 即可。
2.2 整体框架设计
下面我们就来设计一下TCP协议下的服务器类:
- 成员变量需要整体通信的_listensockfd和端口号_port,后续绑定网络通信接口,从中读取连接流。
- 初始化接口InitServer:对端口号进行绑定,将网络通信接口设置为"接听"模式,可以获取外部的链接。
- 循环读取接口Loop:从网络通信接口获取连接流与发送者的信息,之后进行数据接收。
- 服务端口Service:根据获取的连接流和发送者的信息开始读取接收数据
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory>
#include <string>
#include <cstring>
#include <iostream>
#include <functional>
#include <unistd.h>
#include "Log.hpp"
#include "InetAddr.hpp"
using namespace log_ns;
//基础信息
const int gport = 8888;
const int gblocklog = 8;
//错误码
enum
{
SOCKET_FD = 1,
SOCKET_BIND,
SOCKET_LISTNE
};
class TcpServer
{
public:
TcpServer(int port = gport) : _port(port),
_listensockfd(-1),
_isrunning(false)
{
}
// 进行初始化
void InitServer()
{
}
void Loop()
{
}
void Service(int sockfd, InetAddr addr)
{
}
~TcpServer()
{
}
private: