基于TCP协议的服务器

本文介绍了TCP协议的基本概念,包括其作为传输层协议、有连接、可靠传输和面向字节流的特性。接着,详细阐述了TCP服务器的常见API,如socket、bind、listen、accept等操作。还展示了从创建到接受连接的服务器建立过程,以及客户端的连接过程。文章进一步讨论了如何实现一个简单的TCP服务器,以及如何利用线程池优化处理客户端请求,提高服务器效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TCP协议概念

TDP协议是在整个网络分层的传输层的协议,具有以下特性
1.传输层协议
2.有连接
3.可靠传输
4.面向字节流

TCP服务器常见的API

创建 socket 文件描述符(客户端+服务端)

int socket(int domain, int type, int protocol);

damain:IPV4通信,AF_INET
type:类型:面向数据流,选择SOCK_STREAM
protocol:选择0即可
返回值:成功返回一个文件描述符,失败返回-1

绑定端口号 ( 服务器)

int bind(int socket, const struct sockaddr *address,socklen_t address_len);

socket:socket得到的文件描述符
address:struct sockaddr *的一个结构体,一般需要从struct sockaddr_in 结构体强转而来,使用前需初始化
address_len:address结构体的大小
返回值:成功返回0,失败返回-1

开始监听socket (服务器)

int listen(int socket, int backlog);

socket:socket得到的文件描述符
backlog:全连接数 = backlog+1,全连接:即已经建立好,但还没有被accept调用的连接
返回值:成功返回0,失败返回-1

backlog参数的含义


接收请求 ( 服务器)

int accept(int socket, struct sockaddr* address,
socklen_t* address_len);

socket:socket得到的文件描述符
address:结构体
address_len:结构体的大小
返回值:成功返回一个新的文件描述符,这个文件描述符是用于真正通信的,失败返回-1

建立连接 (客户端)

int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);

socket:socket得到的文件描述符
address:结构体,使用之前需初始化
address_len:结构体的大小
返回值:成功返回0,失败返回-1


写入数据(客户端/服务端)

ssize_t write(int fd, const void *buf, size_t count);

fd:文件描述符
buf:写的数据
count:希望写的大小
返回值:实际上写的大小

读取数据(客户端/服务端)

ssize_t read(int fd, void *buf, size_t count);

fd:文件描述符
buf:读的数据
count:希望读的大小
返回值:实际上读的大小

服务端的建立过程
1.socket获取文件描述符
2.bind通过ip,port进行绑定
3.listen将服务器设为监听状态
4.accept,提取出所监听套接字的等待连接队列中第一个连接请求,创建一个新的套接字,并返回指向该套接字的文件描述符,使用该文件描述符进行通信
5.等待客户端输入,再读取数据

客户端的建立过程
1.socket获取文件描述符
2.connect,连接上服务器
3.写入数据

实现TCP服务器

客户端输入数据,服务端读取数据,并将消息回显到客户端上

server.h

#pragma once 
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
using namespace std;
class Server
{
   
	public:
		Server(string _ip,short _port):ip(_ip),port(_port),socketfd(-1)
		{
   }
		~Server()
		{
   
			if(socketfd>=0)
			{
   
				close(socketfd);
			}
		}
	public:
		void InitServer()
		{
   
			socketfd = socket(AF_INET,SOCK_STREAM,0);
			if(socketfd<0)
			{
   
				cerr<<"socket error"<<endl;
				exit(2);
			}
			struct sockaddr_in ser;
			ser.sin_family = AF_INET;
			ser.sin_port = htons(port);
			ser.sin_addr.s_addr = inet_addr(ip.c_str());
			int bd = bind(socketfd,(sockaddr*)&ser,sizeof(ser));
			if(bd<0)
			{
   
				cerr<<"bind error"<<endl;
				exit(3);
			}
			int lis = listen(socketfd,5);
			if(lis<0)
			{
   
				cerr<<"listen error"<<endl;
				exit(4);
			}
		}
		void Run()
		{
   
			struct sockaddr_in peer;
			socklen_t len = sizeof(peer);
			while(1)
			{
   
				int newfd = accept(socketfd,(sockaddr*)&peer,&len);
				if(newfd<0)
				{
   
					cerr<<"accept error"<<endl;
					continue;
				}
				ServerIO(newfd);
			}
		}
		void ServerIO(int fd)
		{
   
			while(1)
			{
   
				char buf[1024] = {
   0};
				ssize_t s = read(fd,buf,sizeof(buf));
				if(s>0)
				{
   
					cout<<"来自client的消息:"<<buf<<endl;
					write(fd,buf,sizeof(buf)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值