//server side
void* s2(void *arg){
info *s = (info*)arg;
char buffer[MAXS];
int k;
sockaddr_in addr;
socklen_t aSize = sizeof(sockaddr_in);
int sfd = accept(s->fd,(sockaddr*)&addr,(socklen_t*)&aSize);
if(sfd<0){
s->current--;
pthread_exit(0);
}
while(1){
k = recv(sfd,buffer,MAXS,0);
cout<<buffer<<"\n";
//1. k ==0 socket has been closed by client
//2. k==-1 error in recv
//3. recv quit
if((k==-1)||(!strncmp(buffer,"quit",4))||(k==0))break;
sprintf(buffer,"%d\n",(int)strlen(buffer)); //Convert length to string using sprintf()
send(sfd,buffer,strlen(buffer),0); //send buffer to client
}
close(sfd);
if(s->limit==s->current)
FD_SET(s->fd,&sfds);
s->current--; //decrement the client number
pthread_exit(0);
}
//client side
1. send(sockfd,"sadhdag",8,0);
2. send(sockfd,"ss",3,0);
Server recv
sadhdag
第一次调用 recv .
第二次调用 recv server recv
ss
dag
服务器端:
函数 s2 由一个线程运行,并通过套接字信息传递参数,在那里接受连接,并在新接受的客户端上调用发送和接收。
为什么会这样?或者如何避免这种情况?
您忽略了
recv()
返回的计数。与评论中的建议相反,没有必要在 memset()
之前将 recv()
缓冲区归零,但 有必要仅在之后 直到该计数 使用该缓冲区。例如:
printf("%s", buffer);
错了,并且
printf("%.*s", count, buffer);
是对的
注意
if((k==-1)||(!strncmp(buffer,"quit",4))||(k==0))break;
也不对。应该是
if((k==-1)||(k==0)||(k >= 4 && !strncmp(buffer,"quit",4))) break;
除非
k
为正,否则查看缓冲区根本无效,除非其中有 are 四个字符,否则比较其中的四个字符是无效的。
您忘记了实际实现任何类型的协议或任何类型的应用程序级逻辑。总结一下:
k = recv(sfd,buffer,MAXS,0);
cout<<buffer<<"\n";
此代码建议您使用换行符终止消息:
sprintf(buffer,"%d\n",(int)strlen(buffer)); //Convert length to string using sprintf()
send(sfd,buffer,strlen(buffer),0); //send buffer to client
如果是这样,那么在另一端解析它的代码在哪里?你把返回的长度扔掉了,所以你甚至不知道要检查哪些字符换行。
TCP 是一种字节流协议,不保留应用程序级消息边界。如果你想用它来发送字符串或其他应用程序级消息,你必须指定并实现一个应用程序级协议来完成它。
你调用
recv
来获取原始 TCP 数据,然后你将它作为一个字符串输出。如果您要定义和实现一个协议来通过 TCP 发送和接收字符串,您必须实际执行此操作。你不能想象它是靠魔法发生的。
如果你想将以换行符结尾的消息接收到 C 风格的字符串中,你当然可以这样做。但是你必须实际编写代码才能做到这一点。