当前位置:网站首页>套接字编程TCP篇
套接字编程TCP篇
2022-06-12 11:11:00 【Diligent_wu】
TCP通信编程
TCP通信编程的流程:
模拟服务端和客户端通信的过程:
接口的使用:
1.创建套接字:
int socket(int domain,int type,int protocol)
domain:地址域 AF_INET/AF_INET6
type:SOCK_STREAM(TCP流式套接字) SOCK_DGRAM(UDP数据报套接字)
protocol:IPPROTO_TCP IPPROTO_UDP
返回socket操作句柄
2.绑定地址信息:
int bind(int sockfd,(struct sockaddr*)addr,socklen_t len)
3.开始监听
listen(int sockfd,int backlog)
sockfd:将哪个socket设置为监听套接字,就传入哪个套接字的句柄
backlog:同一时间的并发连接数,决定同一时间最多接受多少个客户端的连接请求
如果有一个恶意主机同一时间向服务器无限制的发送连接请求,服务端是不是要一直为每一条请求创建套接字?如果是这样,最终只有一个结构就是资源耗尽,系统崩溃。
backlog就是解决这个问题的,前面流程里面说到,监听阶段,监听服务器收到连接请求创建套接字放入未完成连接队列中,绑定好五元组信息后放入已完成连接队列中。
backlog就是决定这个未完成连接队列的节点个数的。但只决定同一时间的节点个数,但不决定系统可以接受的最大客户端连接。
4.获取新建连接
从已完成连接队列中取出一个socket,返回这个socket的操作句柄,这样就可以通信了。
int accept(int sockfd,(struct sockaddr*)cli_addr,socklen* len);
sockfd : 监听套接字,表示要获取哪个tcp服务端套接字的新建连接(可能会有很多TCP服务端)
cli_addr:这个新建套接字的客户端地址信息
len:地址信息长度
返回值:新建套接字的操作句柄 --- 外部程序中的套接字句柄
5.收发数据
ssize_t recv(int sockfd,char* buf,int len,int flag);
默认阻塞,没有数据则等待,连接断开返回0,不在阻塞
ssize_t send(int sockfd,char* data,int len,int flag);
默认阻塞,缓冲区满了则等待,连接断开则出发SIGPIPE异常
6.关闭套接字
close(sockfd); #include<unistd.h>
7.发送连接请求
int connect(int sockfd,struct sockaddr* srv_addr, int len);
srv_addr:服务端的地址信息
connet这个接口中也会描述服务端的地址信息(五元组),所以收发数据只需要直接收发即可。
简易TCP通信流程
socket类的封装
封装一个TcpSocket类,实例化的每一个对象都是一个udp通信连接,通过这个对象的成员方法完成通信流程。
class TcpSocket{
public:
TcpSocket():_sockfd(-1);
bool Socket();
bool Bind(const std::string& ip,uint16_t port);
bool Listen(int backlog = MAX_LISTEN);
bool Accept(TcpSocket* new_sock,std::string* ip =NULL,uint16_t* port);
bool recv(std::string* buf);
bool send(const std::string& data);
bool Close();
bool Connect(const std::string& ip,uint16_t port);
private:
int _sockfd;
#pragma once
#include<iostream>
#include<string>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
using namespace std;
class TcpSocket
{
private:
int sockfd;
public:
TcpSocket()
{
if(!Socket())
{
cout<<"socket create failed"<<endl;
}
}
~TcpSocket()
{
Close();
}
public:
bool Socket()
{
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == 0)
{
cerr<<"scoket error"<<endl;
return false;
}
return true;
}
//有可能错
void Addr(struct sockaddr_in* addr, const string& ip,const uint16_t& port)
{
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
addr->sin_addr.s_addr = inet_addr(ip.c_str());
}
bool Bind(const string& ip,const uint16_t& port)
{
struct sockaddr_in addr;
Addr(&addr,ip,port);
socklen_t len = sizeof(addr);
int ret = bind(sockfd,(struct sockaddr*)&addr,len);
if(ret < 0)
{
cerr<<"bind errror"<<endl;
return false;
}
return true;
}
bool Listen()
{
int ret = listen(sockfd,5);
if(ret == -1)
{
cerr<<"listen error"<<endl;
return false;
}
return true;
}
bool Connect(const string& ip,const uint16_t& port)
{
struct sockaddr_in addr;
Addr(&addr,ip,port);
socklen_t len = sizeof(addr);
int ret = connect(sockfd,(struct sockaddr*)&addr,len);
if(ret < 0)
{
cerr<<"connect error"<<endl;
return false;
}
return true;
}
bool Accept(TcpSocket* new_sock,string* ip = NULL,uint16_t* port = NULL)
{
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
int newfd = accept(sockfd,(struct sockaddr*)&addr,&len);
if(newfd < 0)
{
cerr<<"accept error"<<endl;
return false;
}
new_sock->sockfd = newfd;
if(ip != NULL)
{
*ip = inet_ntoa(addr.sin_addr);
}
if(port != NULL)
{
*port = ntohs(addr.sin_port);
}
return true;
}
bool Recv(string* buf)
{
char tmp[4096] = {
0};
int ret = recv(sockfd,tmp,4095,0);;
if(ret <0)
{
cerr<<"recv error"<<endl;
return false;
}
*buf = tmp;
buf->assign(tmp);
return true;
}
bool Send(const string& data)
{
//UDP是数据报传输,整条交付
//而TCP是字节流传输,能传输多少就传输多少,对数据边界并没有进行区分
//如果对方的缓冲区只剩了50个字节的空间,send给对方100个字节,就只能成功发送50个字节,并返回传送大小50字节
size_t total = 0 ;
while(total < data.size())
{
int ret = send(sockfd,&data[0]+total,data.size()-total,0);
if(ret < 0)
{
cerr<<"send error"<<endl;
return false;
}
total+=ret;
}
return true;
}
bool Close()
{
close(sockfd);
return true;
}
};
边栏推荐
- AcWing 131. The largest rectangle in the histogram (monotone stack classic application template)
- Amélioration de la 3dsc par HSC
- DrQueueOnRails 集成 LDAP 验证
- AcWing 1995. Meet and greet (simulation)
- The solution of Lenovo notebook ThinkPad t440 WiFi dropping all the time
- ^33 variable promotion and function promotion interview questions
- Get start date and end date for all quarters of the year
- 人脸识别pip 安装dlib库失败
- 模块8作业
- PHP specifies the number of people to distribute the specified amount equally at random (scaling method)
猜你喜欢

Grid layout

InfoQ geek media's 15th anniversary solicitation |position:fixed virtual button cannot take effect after being triggered. Problem analysis and Solution Exploration

Leetcdoe 2037. Make each student have the minimum number of seat movements (yes, once)

ReentrantLock源码分析

AcWing 128. Editor (to effectively modify the specified position in the top stack)

读mysql45讲-自我总结(部分)

M-arch (fanwai 11) gd32l233 evaluation PWM driven active buzzer

Malicious code analysis practice - use IDA pro to analyze lab05-01 dll

蓝桥杯2015年CA省赛(填坑中)

AcWing 131. The largest rectangle in the histogram (monotone stack classic application template)
随机推荐
Reading mysql45 lecture - self summary (part)
重量级代理缓存服务器Squid
Find the location of a function in PHP
AcWing 1986. 镜子(模拟,环图)
FPGA-按键实验
Redis keys in PHP
深度学习与CV教程(14) | 图像分割 (FCN,SegNet,U-Net,PSPNet,DeepLab,RefineNet)
file_ get_ Contents() JSON after reading_ Decode cannot be converted to array
【CF1392D】D. Omkar and Bed Wars(环形与后效性dp)
MCUXpresso开发NXP RT1060(3)——移植LVGL到NXP RT1060
SOT23(Small Outline Transistor)
ReentrantLock源码分析
Amélioration de la 3dsc par HSC
AcWing 1995. 见面与问候(模拟)
M-arch (fanwai 11) gd32l233 evaluation PWM driven active buzzer
AcWing 128. Editor (to effectively modify the specified position in the top stack)
Common tools download address
FPGA key experiment
M-arch (fanwai 13) gd32l233 evaluation - some music
CLJ3-100ALH30剩余电流继电器