linux c socket 客户端循环十次向服务器发送数据(tcp连接),为啥只能接受第一次的?求代码

linux c socket 客户端循环十次向服务器发送数据(tcp连接),为啥只能接受第一次的?求代码,第1张

只是做这些动作的话不需要多线程

找了下以前写的 改成了你说的10次发送

client.c:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<errno.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

int main(int argc,char **argv)

{

char wbuf[] = "hello server"

char rbuf[128]

int i

int sock

struct sockaddr_in server = {0}

struct timeval timeo

timeo.tv_sec = 0

timeo.tv_usec = 1000 * 1000 //

socklen_t len = sizeof(timeo)

if( argc != 2)

{

printf("usage: ./client <ipaddress>\n")

return -1

}

sock = socket(AF_INET, SOCK_STREAM, 0)

if(sock <0)

{

perror("Create TCP Socket")

return -1

}

setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeo, len)

server.sin_family = AF_INET

server.sin_port = htons(30000)

inet_pton(AF_INET, argv[1], &(server.sin_addr))

int res = connect(sock, (struct sockaddr*)&server, sizeof(server))

if (res <0)

{

if(res == EINPROGRESS)

perror("connecting stream socket time out:")

else

perror("connecting stream socket error:")

close(sock)

return -1

}

else

{

printf("Connect Server@%s\n",argv[1])

for(i=0i<10i++)

{

int wsize = send(sock,wbuf,sizeof(wbuf),0)

if(wsize<=0)

{

perror("write error:")

close(sock)

return -1

}

printf("1111111i=%d\n",i)

while(1)

{

int rsize=recv(sock,rbuf,sizeof(rbuf),0)

if(rsize>0)

{

rbuf[rsize]='\0'

printf("recv msg from server: %s\n",rbuf)

break

}

if(rsize<0)

{

close(sock)

perror("read error:")

return -1

}

}

}

close(sock)

return 0

}

}

server.c:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<errno.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

int main(int argc, char** argv)

{

intlistenfd, connfd

struct sockaddr_in servaddr = {0}

charrbuf[128]

charwbuf[] = "hello client"

int n

if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )

{

perror("Create TCP Socket")

return -1

}

servaddr.sin_family = AF_INET

servaddr.sin_addr.s_addr = htonl(INADDR_ANY)

servaddr.sin_port = htons(30000)

if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1)

{

perror("bind socket error:")

return -1

}

if( listen(listenfd, 10) == -1)

{

perror("listen socket error:")

return -1

}

printf("======waiting for client's request======\n")

while(1)

{

if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1)

{

perror("accept socket error:")

continue

}

while(1)

{

n = recv(connfd, rbuf, sizeof(rbuf), 0)

if(n>0)

{

rbuf[n] = '\0'

printf("recvmsg from client: %s\n", rbuf)

n = send(connfd, wbuf, sizeof(wbuf),0)

if(n<=0)

{

perror("sned error:")

close(connfd)

break

}

}

else if(n <0)

{

perror("recv error:")

close(connfd)

break

}

}

close(connfd)

}

close(listenfd)

return 0

}

运行的时候 client

./client 你的serverip

端口我用的30000 写死在程序里了

粘包是因为发送太快了,可以通过发送固定长度数据和在数据包前后加标识以做截取解决。

给你介绍第一种方法,发送固定长度的数据包,不足长度的补数,这种方法要固定读取N长度的数据

整体说按类型分,可以分为头包,一般包,尾包

这三种数据包的格式可以这样包头+实际数据+检验位

1. 头包,比如可以是A01:LXXXXXXXXXXXC

包头可以用包头标识+第几帧+开始截取标志+文件长度L构成,例子中是A01:),L为所有数据包加起来的实际数据总长度,XXXXXXXX为实际数据占 N字节(N为固定字节,这个你自己定义大小),C为校验位占一个字节,即所有数据的累加和

2. 一般包,格式可以为P02:XXXXXXXXXXXXC

类似包头格式,P为一般包标识,02表示第二个包

3 包尾,格式可以为D03:XXXXXFFFFFFC

此处XXXXX为实际数据,FFFFF为不足N位的补数,最后一个包是多长可以通过头包L跟尾包算出来

各种校验

1. 收到的数据包要做校验位验证,就是格式中的C

2. 每次收到包要判断是不是期望的包,通过第几个包来判断,比如你要收第4个包了,但你收到了P05,那就重新请求一次要收第四个包,或者是直接失败

3 其他校验,具体情况具体分析

第二种数据包前后加标识以做截取解决也是类似的,就是在实际数据前后加上一些供你判断的标识,思路已经在这里了,具体格式要自己定义,因为你是程序员


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9575024.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-29
下一篇 2023-04-29

发表评论

登录后才能评论

评论列表(0条)

保存