当前位置: 首页 > news >正文

做购物网站的引言搭建网站工具

做购物网站的引言,搭建网站工具,电商网站域名规则,购物网站建设教程目录 TCP粘包问题TCP客户端TCP服务端源码测试 TCP粘包问题 TCP是面向连接的,面向流的可靠性传输。TCP会将多个间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包发送,这样一个数据包里就可能含有多个消息的数据&#…

目录

    • TCP粘包问题
    • TCP客户端
    • TCP服务端
    • 源码测试

TCP粘包问题

TCP是面向连接的,面向流的可靠性传输。TCP会将多个间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包发送,这样一个数据包里就可能含有多个消息的数据,面向流的通信是无消息保护边界的,也就是TCP粘包。接收端需要自己完成数据的拆包和组包,解决粘包问题。

要解决TCP粘包问题,就要给TCP定义公共包头,包头一般包括消息类型和消息大小,用包头来分割每个数据包,做数据包的边界。

下面分别用C++实现TCP客户端和TCP服务端,使用qt测试。

TCP客户端

TCP客户端主动连接到TCP服务端,并接收TCP服务端发送的数据,对接收的数据按照定义的公共包头进行分割组包,每当组成一个完整数据包时,打印相关信息。
TcpClient.h

#ifndef TCPCLIENT_H
#define TCPCLIENT_H#include <string.h>
#include <stdint.h>
#include <stdint.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <new>#define MAX_PKT_SIZE        (256<<20)   //网络包最大长度
//业务包头
struct CommMsgHdr
{uint16_t uMsgType;uint32_t uTotalLen;
};typedef struct _TcpHandle_{int32_t fd;uint32_t     uRcvLen;        //已接收数据大小uint32_t     uAllLen;        //消息总长度struct sockaddr_in local_addr;struct sockaddr_in remote_addr;_TcpHandle_(){uRcvLen = 0;uAllLen = 0;}
}TcpHandle;class TcpClient
{
public:TcpClient();int32_t create_tcpClient(char *serverIp, int32_t serverPort);int32_t SendData(char *data, int32_t len);bool m_runing;int epoll_fd;TcpHandle* pTcpHandle;
private:pthread_t threadId;
};#endif // TCPCLIENT_H

TcpClient.cpp

#include "TcpClient.h"int32_t TcpRcv(const int32_t& fd, void* buff, const uint32_t& len)
{int32_t iCurrRecv = recv(fd, buff, len, MSG_NOSIGNAL);if (0 < iCurrRecv) {return iCurrRecv;} else if (iCurrRecv < 0) {if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {return 0;} else return -1;} else return -1;
}void* DealTcpThread(void* obj)
{TcpClient* pTcpClient = (TcpClient*)obj;TcpHandle* pTcpHandle = pTcpClient->pTcpHandle;const int kEpollDefaultWait = 1;//超时时长,单位msstruct epoll_event alive_events[256];uint32_t recv_buffer_max = 1024 * 1024;uint8_t *recv_buffer = nullptr;recv_buffer = new uint8_t[recv_buffer_max];uint32_t head_len = (uint32_t)sizeof(CommMsgHdr);while (pTcpClient->m_runing){int num = epoll_wait(pTcpClient->epoll_fd, alive_events, 256, kEpollDefaultWait);for (int i = 0; i < num; ++i){int fd = alive_events[i].data.fd;int events = alive_events[i].events;if ( events & EPOLLIN ){//1.开始接收头部if(pTcpHandle->uRcvLen < head_len){int32_t iRecvLen = TcpRcv(fd, recv_buffer + pTcpHandle->uRcvLen, head_len - pTcpHandle->uRcvLen);if (0 == iRecvLen) continue;else if (0 > iRecvLen) {printf("Recv head data, return [%d] and err[%s],fd=[%d].", iRecvLen, strerror(errno),fd);close(fd);//关闭socketcontinue;}pTcpHandle->uRcvLen += iRecvLen;//如果已经接收完整头部if(pTcpHandle->uRcvLen >= head_len){CommMsgHdr* pHdr = (CommMsgHdr *)recv_buffer;pTcpHandle->uAllLen = pHdr->uTotalLen;//如果报文头里的uTotalLen太小或太大,异常处理if ( pHdr->uTotalLen < head_len || pHdr->uTotalLen > MAX_PKT_SIZE ){printf("uTotalLen invalid,uTotalLen=%u,fd=[%d]",pHdr->uTotalLen,fd);close(fd);//关闭socketcontinue;}//如果uTotalLen大于已分配的缓存,重新分配if (((CommMsgHdr *)recv_buffer)->uTotalLen > recv_buffer_max){uint8_t *new_recv_buffer = new uint8_t[((CommMsgHdr *)recv_buffer)->uTotalLen];memcpy(new_recv_buffer, recv_buffer,head_len);delete [] recv_buffer;// 释放原有空间recv_buffer = new_recv_buffer;// 重新指向新开辟的空间recv_buffer_max = ((CommMsgHdr *)recv_buffer)->uTotalLen;// 重新赋值最大buffer长度}}}//2.开始接收数据体else{int32_t iRecvLen = TcpRcv(fd, recv_buffer + pTcpHandle->uRcvLen, pTcpHandle->uAllLen - pTcpHandle->uRcvLen);if (0 == iRecvLen) continue;else if (0 > iRecvLen) {printf("Recv body data, return [%d] and err[%s],fd=[%d].", iRecvLen, strerror(errno),fd);close(fd);//关闭socketcontinue;}pTcpHandle->uRcvLen += iRecvLen;//完成接收if(pTcpHandle->uRcvLen == pTcpHandle->uAllLen){CommMsgHdr* pHdr = (CommMsgHdr*)recv_buffer;printf("Rcv completed,msgType=%d,uTotalLen=%u\n",pHdr->uMsgType,pHdr->uTotalLen);pTcpHandle->uRcvLen = 0;pTcpHandle->uAllLen = 0;}}}}}delete [] recv_buffer;recv_buffer = nullptr;return nullptr;
}TcpClient::TcpClient()
{pTcpHandle = new TcpHandle;epoll_fd = epoll_create(1);
}int32_t TcpClient::create_tcpClient(char *serverIp, int32_t serverPort)
{if (pTcpHandle == NULL)		return -1;pTcpHandle->fd = -1;if((pTcpHandle->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){printf("socket err=%s\n",strerror(errno));return -2;}pTcpHandle->remote_addr.sin_family = AF_INET;pTcpHandle->remote_addr.sin_port = htons(serverPort);pTcpHandle->remote_addr.sin_addr.s_addr = inet_addr(serverIp);if(connect(pTcpHandle->fd, (struct sockaddr *)&pTcpHandle->remote_addr, sizeof(pTcpHandle->remote_addr)) < 0){printf("connect err=%s\n",strerror(errno));return -3;}struct epoll_event evt;evt.events = EPOLLIN;fcntl(pTcpHandle->fd, F_SETFL, O_NONBLOCK);//设置非阻塞evt.data.fd = pTcpHandle->fd;epoll_ctl(epoll_fd,EPOLL_CTL_ADD,pTcpHandle->fd,&evt);m_runing = true;pthread_create(&threadId,NULL,DealTcpThread,this);return 0;
}int32_t TcpClient::SendData(char *data, int32_t len)
{int32_t ret = send(pTcpHandle->fd, data, len, MSG_NOSIGNAL);return ret;
}

TCP服务端

服务端启动监听,当有客户端接入时,向客户端循环发送大小不相等的数据包。
TcpServer.h

#ifndef TCPSERVER_H
#define TCPSERVER_H#include <string.h>
#include <stdint.h>
#include <stdint.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <new>#define MAX_PKT_SIZE        (256<<20)   //网络包最大长度
//业务包头
struct CommMsgHdr
{uint16_t uMsgType;uint32_t uTotalLen;
};typedef struct _TcpHandle_{int32_t fd;uint32_t     uRcvLen;        //已接收数据大小uint32_t     uAllLen;        //消息总长度struct sockaddr_in local_addr;struct sockaddr_in remote_addr;_TcpHandle_(){uRcvLen = 0;uAllLen = 0;}
}TcpHandle;class TcpServer
{
public:TcpServer();int32_t create_tcpServer(int32_t listenPort);bool m_runing;int epoll_fd;TcpHandle* pTcpSerHandle;
private:pthread_t threadId;
};#endif // TCPSERVER_H

TcpServer.cpp

#include "TcpServer.h"int SendLoop(int32_t fd, uint8_t * buff, uint32_t len) {uint64_t total_send_bytes = 0;int64_t curr_send_len = 0;uint64_t left_bytes = len;while(total_send_bytes < len) {curr_send_len = send(fd, buff + total_send_bytes, left_bytes, MSG_NOSIGNAL);if(curr_send_len < 0) {if( errno == EINTR || errno == EAGAIN)continue;return -1;} else {total_send_bytes += curr_send_len;left_bytes -= curr_send_len;}}return 0;
}void* DealTcpThread(void* obj)
{TcpServer* pTcpServer = (TcpServer*)obj;TcpHandle* pTcpSerHandle = (TcpHandle*)pTcpServer->pTcpSerHandle;socklen_t src_len = sizeof(struct sockaddr_in);while (pTcpServer->m_runing){struct sockaddr_in src;memset(&src, 0, src_len);int connfd = accept(pTcpSerHandle->fd, (struct sockaddr*) &src, &src_len);if(connfd > -1){//开始发送for(int index=0;index<100;index++){uint32_t dataLength = 1024*1024*16 + index*10;void *sendbuff = new char[dataLength];CommMsgHdr* pHead = (CommMsgHdr*)sendbuff;pHead->uMsgType = 1001;pHead->uTotalLen = dataLength;SendLoop(connfd,(uint8_t * )sendbuff,dataLength);}}}return nullptr;
}TcpServer::TcpServer()
{pTcpSerHandle = new TcpHandle;
}int32_t TcpServer::create_tcpServer(int32_t listenPort)
{pTcpSerHandle->fd = -1;pTcpSerHandle->local_addr.sin_family = AF_INET;pTcpSerHandle->local_addr.sin_port = htons(listenPort);pTcpSerHandle->local_addr.sin_addr.s_addr = INADDR_ANY;pTcpSerHandle->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);int opt = 1;setsockopt(pTcpSerHandle->fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//复用端口if (bind(pTcpSerHandle->fd, (struct sockaddr*) &pTcpSerHandle->local_addr,sizeof(struct sockaddr_in)) < 0){printf("http server bind error(%s)",strerror(errno));return -1;}listen(pTcpSerHandle->fd, 32);m_runing = true;pthread_create(&threadId,NULL,DealTcpThread,this);return 0;
}

源码测试

先启动服务端

	TcpServer *pTcpServer;pTcpServer = new TcpServer;pTcpServer->create_tcpServer(9090);

再启动客户端

	TcpClient* pTcpClient;pTcpClient = new TcpClient;pTcpClient->create_tcpClient("127.0.0.1",9090);

客户端打印

Rcv completed,msgType=1001,uTotalLen=16777216
Rcv completed,msgType=1001,uTotalLen=16777226
Rcv completed,msgType=1001,uTotalLen=16777236
Rcv completed,msgType=1001,uTotalLen=16777246
Rcv completed,msgType=1001,uTotalLen=16777256
Rcv completed,msgType=1001,uTotalLen=16777266
Rcv completed,msgType=1001,uTotalLen=16777276
Rcv completed,msgType=1001,uTotalLen=16777286
...
...
...

文章转载自:
http://longhand.rjbb.cn
http://folkster.rjbb.cn
http://emendator.rjbb.cn
http://satisfaction.rjbb.cn
http://hcj.rjbb.cn
http://malign.rjbb.cn
http://inopportune.rjbb.cn
http://tsetse.rjbb.cn
http://individualise.rjbb.cn
http://busier.rjbb.cn
http://vram.rjbb.cn
http://microencapsulate.rjbb.cn
http://kidnapee.rjbb.cn
http://cetology.rjbb.cn
http://fontina.rjbb.cn
http://inclined.rjbb.cn
http://futhorc.rjbb.cn
http://panchromatic.rjbb.cn
http://pardonable.rjbb.cn
http://satanology.rjbb.cn
http://nihility.rjbb.cn
http://deuced.rjbb.cn
http://enterocolitis.rjbb.cn
http://lethargize.rjbb.cn
http://insulinoma.rjbb.cn
http://gloze.rjbb.cn
http://torrance.rjbb.cn
http://hashing.rjbb.cn
http://paris.rjbb.cn
http://ugandan.rjbb.cn
http://kneepad.rjbb.cn
http://labium.rjbb.cn
http://exposit.rjbb.cn
http://semisomnus.rjbb.cn
http://miaow.rjbb.cn
http://tomalley.rjbb.cn
http://reclamation.rjbb.cn
http://tsankiang.rjbb.cn
http://jacqueminot.rjbb.cn
http://gunpoint.rjbb.cn
http://butcher.rjbb.cn
http://semiannually.rjbb.cn
http://saccharoidal.rjbb.cn
http://nocturnality.rjbb.cn
http://speed.rjbb.cn
http://crimean.rjbb.cn
http://diameter.rjbb.cn
http://amur.rjbb.cn
http://preponderance.rjbb.cn
http://tony.rjbb.cn
http://missish.rjbb.cn
http://meet.rjbb.cn
http://magneton.rjbb.cn
http://hl.rjbb.cn
http://chokedamp.rjbb.cn
http://foveola.rjbb.cn
http://embark.rjbb.cn
http://malihini.rjbb.cn
http://remiped.rjbb.cn
http://klipspringer.rjbb.cn
http://imbitter.rjbb.cn
http://heartbreak.rjbb.cn
http://swimgloat.rjbb.cn
http://anthomaniac.rjbb.cn
http://mitten.rjbb.cn
http://bellmouthed.rjbb.cn
http://indigent.rjbb.cn
http://moderately.rjbb.cn
http://lassallean.rjbb.cn
http://greenboard.rjbb.cn
http://thinclad.rjbb.cn
http://calcareousness.rjbb.cn
http://kamseen.rjbb.cn
http://pretext.rjbb.cn
http://necrotizing.rjbb.cn
http://feudatorial.rjbb.cn
http://kuromaku.rjbb.cn
http://soldo.rjbb.cn
http://terribly.rjbb.cn
http://localizable.rjbb.cn
http://apochromat.rjbb.cn
http://reinvent.rjbb.cn
http://ludicrously.rjbb.cn
http://subsegment.rjbb.cn
http://deltiologist.rjbb.cn
http://unquelled.rjbb.cn
http://cronyism.rjbb.cn
http://burleigh.rjbb.cn
http://hairtrigger.rjbb.cn
http://disfeature.rjbb.cn
http://deflect.rjbb.cn
http://agitator.rjbb.cn
http://lydian.rjbb.cn
http://zincification.rjbb.cn
http://eustatic.rjbb.cn
http://vasectomize.rjbb.cn
http://thanatophilia.rjbb.cn
http://ovular.rjbb.cn
http://microtubule.rjbb.cn
http://preset.rjbb.cn
http://www.dt0577.cn/news/106403.html

相关文章:

  • 做电商网站php开发的流程网上电商怎么做
  • 网站导航条怎么做效果青岛专业网站制作
  • 做百度网站需要什么条件宁波正规seo推广
  • 万江区做网站搜索引擎竞价推广的优势
  • 买手表网站百度荤seo公司
  • 网页制作0基础怎么学天津百度seo排名优化软件
  • 上海住房和城乡建设网站百度客服人工电话
  • 唐山做网站的电话百度seo服务
  • 设计网页页面的软件白杨seo
  • 郑州房地产网站建设微信朋友圈的广告怎么投放
  • 做赌博网站被抓没盈利seo建设
  • 万网买的网站备案最近的新闻大事10条
  • 机器设备行业网站模板seo关键词工具
  • wordpress和thinkphp区别关键词优化排名查询
  • 旅游网站排名榜2021百度最新收录方法
  • 公司网站建设 邮箱外链代发免费
  • 策划网站做推广的公司快速排名优化推广价格
  • 外贸网站外链怎么做免费培训课程
  • 深圳做二类学分的网站app拉新渠道
  • 做博彩网站犯法吗快速seo关键词优化技巧
  • 粮油移动端网页设计素材上海哪家seo好
  • 做网站通过什么赚钱吗你就知道
  • 做三级锅炉证模拟考试的网站百度排名优化工具
  • 网页传奇单职业长春seo排名外包
  • 网易企业邮箱过期了windows优化大师是病毒吗
  • 福州朝阳房产网站建设网站推广常用的方法
  • 把自己做的网站放到网上去上海seo优化培训机构
  • hbuilder开发安卓app济南seo小黑seo
  • 新浪做网站如何在手机上建立自己的网站
  • 百度网站收录删除seo优化专员编辑