最全TCP利用封包和解包解决“粘包”问题_tcp粘包源码c实现(1),快点来学吧

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

/
/

该函数能够发送指定长度的数据。一次发送不完,可以接着发送,直到发送完指定长度为止
*/
int MySend( int iSock, char * pchBuf, size_t tLen){
int iThisSend;
unsigned int iSended=0;//has send bytes
if(tLen == 0)
return(0);
while(iSended<tLen){
do{
iThisSend = send(iSock, pchBuf, tLen-iSended, 0);//this time
} while((iThisSend<0) && (errno==EINTR));
if(iThisSend < 0){
return(iSended);
}
iSended += iThisSend;
pchBuf += iThisSend;
}
return(tLen);
}

#define DEFAULT_PORT 6666

int main( int argc, char * argv[]){
int connfd = 0;
int cLen = 0;
struct sockaddr_in client;
if(argc < 2){
printf(" Uasge: clientent [server IP address]\n");
return -1;
}
client.sin_family = AF_INET;
client.sin_port = htons(DEFAULT_PORT);
client.sin_addr.s_addr = inet_addr(argv[1]);
connfd = socket(AF_INET, SOCK_STREAM, 0);
if(connfd < 0){
printf(“socket() failure!\n” );
return -1;
}

if(connect(connfd, (struct sockaddr*)&client, sizeof(client)) < 0){
    printf("connect() failure!\n" );
    return -1;
}
//
ssize_t writeLen;
char *sendMsg = "0123456789";
int tLen=strlen(sendMsg);
printf("tLen:%d\n" ,tLen);
int iLen=0;
char * pBuff= new char [100];
*(int*)(pBuff+iLen)= htonl(tLen);
iLen+=sizeof( int);
memcpy(pBuff+iLen,sendMsg,tLen);
iLen+=tLen;
writeLen= MySend(connfd, pBuff, iLen);
if (writeLen < 0) {
   printf("write failed\n" );
   close(connfd);
   return 0;
}
else{
   printf("write sucess, writelen :%d, sendMsg:%s\n",writeLen,sendMsg);
}
close(connfd);
return 0;

}


服务器端:



#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>

/*
该函数能够接受指定长度(字节)的数据。循环接收,直到接受完指定数量为止。
*/
int MyRecv( int iSock, char * pchBuf, size_t tCount){
size_t tBytesRead=0;
int iThisRead;
while(tBytesRead < tCount){
do{
iThisRead = read(iSock, pchBuf, tCount-tBytesRead);
} while((iThisRead<0) && (errno==EINTR));
if(iThisRead < 0){
return(iThisRead);
}else if (iThisRead == 0)
return(tBytesRead);
tBytesRead += iThisRead;
pchBuf += iThisRead;
}
}

#define DEFAULT_PORT 6666
int main( int argc, char ** argv){
int sockfd,acceptfd; /* 监听socket: sock_fd,数据传输socket: acceptfd /
struct sockaddr_in my_addr; /
本机地址信息 /
struct sockaddr_in their_addr; /
客户地址信息 */
unsigned int sin_size, myport=6666, lisnum=10;
if ((sockfd = socket(AF_INET , SOCK_STREAM, 0)) == -1) {
perror(“socket” );
return -1;
}

printf("socket ok \n");
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(DEFAULT_PORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 0);

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr )) == -1) {
    perror("bind" );
    return -2;
}

printf("bind ok \n");
if (listen(sockfd, lisnum) == -1) {
    perror("listen" );
    return -3;
}
printf("listen ok \n");
char recvMsg[10];
sin_size = sizeof(my_addr);
acceptfd = accept(sockfd,(struct sockaddr *)&my_addr,&sin_size);
if (acceptfd < 0) {
   close(sockfd);
   printf("accept failed\n" );
   return -4;
}

ssize_t readLen = MyRecv(acceptfd, recvMsg, sizeof( int));
if (readLen < 0) {
   printf("read failed\n" );
   return -1;
}

int len=( int)ntohl(*( int*)recvMsg);
printf("len:%d\n",len);
readLen = MyRecv(acceptfd, recvMsg, len);
if (readLen < 0) {
   printf("read failed\n" );
   return -1;
}
recvMsg[len]='\0';//接收到的数据并没有结束符'\0',因此需要加上结束符'\0
printf("recvMsg:%s\n" ,recvMsg);
close(acceptfd);
return 0;

}


Makefile:



all:tcpServer tcpClient
tcpServer:tcpServer.o
gcc -g -o tcpServer tcpServer.o
tcpClient:tcpClient.o
gcc -g -o tcpClient tcpClient.o
tcpServer.o:tcpServer.c
gcc -g -c tcpServer.c
tcpClient.o:tcpClient.c
gcc -g -c tcpClient.c
clean:all
rm all


运行截图:  
 ![这里写图片描述](https://img-blog.csdn.net/20180427173853791?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM0NTcxNjc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


四、总结思考



> 
> 2018年11月3日补充
> 
> 
> 


其实,这篇文章一个非常核心的代码就是readn和writen函数,说白了, 就一直读, 读到指定的字节数为止。 其实, 在recv函数中, 最后参数如果是MSG\_WAITALL, 那么就可以用recv函数一行代码, 替代上述所有代码, 棒棒哒。  
 参考:[read函数](https://bbs.csdn.net/topics/618668825)  
 大家可以对比下代码:



ssize_t readn(int fd, void *buf, int n)
{
size_t nleft = n; // left的意思是“剩下”, 而非“左边”
char *bufptr = buf;
ssize_t nread;
while(nleft > 0)
{
if((nread = read(fd, bufptr, n)) < 0)
{
if(errno == EINTR) // 遇到中断
{
continue; // 或者用 nread = 0;
}
else

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

mg-XsypbUtJ-1715818915661)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 易语言是一种可视化编程语言,用于开发Windows平台的应用程序。封包工具是指用于将数据进行打和拆的工具,主要用于网络编程中数据的传输和通信。 易语言中有一些第三方库和插件可以用于实现TCP封包的功能。这些库和插件提供了一些函数和方法,方便开发人员在易语言中进行数据的封包和解TCP封包是将数据按照一定的格式进行打,以便于在网络上进行传输。常用的封包格式有固定长度封包、变长封包和自定义格式封包等。使用易语言进行TCP封包时,可以使用这些第三方库和插件中提供的函数,按照指定的封包格式将数据进行打TCP是将封包后的数据拆分成可识别的数据。解操作与封包相反,通过读取封包中的长度字段和标识字段等信息,将封包还原为原始数据。易语言中的TCP工具可以根据封包格式的规则进行解操作,并将解后的数据返回给开发人员使用。 使用易语言进行TCP封包的工具可以帮助开发人员简化数据传输的过程,提高开发效率和数据传输的安全性。通过这些工具,开发人员可以方便地进行数据的封包和解操作,从而更好地实现网络通信功能。 ### 回答2: 易语言是一种编程语言,它可以用于开发Windows系统下的应用程序。TCP封包工具是易语言提供的一个工具,用于处理TCP协议传输的数据。 在网络通信中,数据的传输是以数据的形式进行的。TCP封包工具可以帮助程序员处理从网络接收到的数据,以及将要发送的数据转换为合适的格式进行传输。 封包指的是将数据转换为特定格式的过程。TCP封包工具可以将数据按照协议要求的格式进行封装,例如添加报文头部、计算校验和等操作,以便正确地发送给对方。 解指的是将接收到的数据进行解析的过程。TCP封包工具可以按照协议规定的格式解析数据,并提取出其中的有效信息,以便程序能够正确地处理这些数据。 TCP封包工具可以帮助程序员简化网络通信的开发过程,使得开发人员能够更加专注于实现业务逻辑。它提供了一套封包的接口和函数库,开发者只需要调用相应的函数来完成数据的封包和解操作即可。 总之,易语言TCP封包工具是易语言提供的一个工具,用于处理TCP协议传输的数据,使开发者能够更加方便地进行网络通信的开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值