用C语言编写带循环的套接字程序发送和接收消息
我刚刚开始学习socket编程,我正在尝试使用TCP在客户端和服务器之间发送和接收数据。首先,我从服务器向客户机发送当前目录的大小,而客户机接收到的结果非常好。然后我想从服务器直接发送当前文件中的每个文件名,因此我创建了一个循环来执行此操作。在客户机中,我还有一个循环,用于接收所有文件名,这些文件名执行的次数与文件的次数(目录大小)相同。问题是,当我打印出在循环中接收到的内容时,缓冲区是空白的。我意识到第一个循环接收的字节是55,其余的是0,但缓冲区总是空的。以下是我的代码片段: 服务器:用C语言编写带循环的套接字程序发送和接收消息,c,sockets,network-programming,C,Sockets,Network Programming,我刚刚开始学习socket编程,我正在尝试使用TCP在客户端和服务器之间发送和接收数据。首先,我从服务器向客户机发送当前目录的大小,而客户机接收到的结果非常好。然后我想从服务器直接发送当前文件中的每个文件名,因此我创建了一个循环来执行此操作。在客户机中,我还有一个循环,用于接收所有文件名,这些文件名执行的次数与文件的次数(目录大小)相同。问题是,当我打印出在循环中接收到的内容时,缓冲区是空白的。我意识到第一个循环接收的字节是55,其余的是0,但缓冲区总是空的。以下是我的代码片段: 服务器: if
if(strcmp(buffer, "ls-remote") == 0){ //display files from server directory
// get the size of the directory
unsigned long size = htonl(directorySize());
n = send(newsockfd, &size, sizeof(size), 0);
if(n < 0) syserr("can't send to server");
DIR *d = opendir(".");
struct dirent *dir;
if (d)
{
while((dir = readdir(d))!= NULL)
{ memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
strcat(buffer, dir->d_name);
n = send(newsockfd, buffer, strlen(buffer), 0);
if(n < 0) syserr("can't send to server");
}
closedir(d);
}
else{
syserr("Error...could not get files from directory.");
}
}
if(strcmp(buffer,“ls remote”)==0{//显示服务器目录中的文件
//获取目录的大小
无符号长大小=htonl(directorySize());
n=发送(newsockfd,&size,sizeof(size),0);
如果(n<0)syserr(“无法发送到服务器”);
DIR*d=opendir(“.”);
结构方向*dir;
如果(d)
{
而((dir=readdir(d))!=NULL)
{memset(&buffer[0],0,sizeof(buffer));//清除缓冲区
strcat(缓冲区,目录->数据单元名称);
n=发送(newsockfd,buffer,strlen(buffer),0);
如果(n<0)syserr(“无法发送到服务器”);
}
closedir(d);
}
否则{
syserr(“错误…无法从目录获取文件。”);
}
}
客户:
if(strcmp(buffer, "ls-remote") == 0){ //display files from server directory
unsigned long size;
n = recv(sockfd, &size, sizeof(uint32_t), 0);// recieve the size of the directory
if(n < 0) syserr("can't receive from server");
size = ntohl(size);
while(size > 0){
memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
n = recv(sockfd, buffer, 255, 0); // recieve directory from server
if(n < 0) syserr("can't send to server");
buffer[strlen(buffer) - 1] = '\0';
printf("recieving: %s\n", buffer); // print directory
size--;
}
}
if(strcmp(buffer,“ls remote”)==0{//显示服务器目录中的文件
无符号长尺寸;
n=recv(sockfd,&size,sizeof(uint32_t),0);//接收目录的大小
如果(n<0)syserr(“无法从服务器接收”);
尺寸=ntohl(尺寸);
而(大小>0){
memset(&buffer[0],0,sizeof(buffer));//清除缓冲区
n=recv(sockfd,buffer,255,0);//从服务器接收目录
如果(n<0)syserr(“无法发送到服务器”);
缓冲区[strlen(buffer)-1]='\0';
printf(“接收:%s\n”,缓冲区);//打印目录
大小--;
}
}
这里的一个问题是,发送目录和目录项大小的服务器与接收它们的客户端之间没有同步。换句话说,如果目录包含entry.1、entry.2和entry.3,则客户端可能会收到entry.1和entry.2entry.3,或者entry.1entry.2和entry.3。即使unicode不是罪魁祸首,正如JVene所建议的那样,这也是事实
还有几件事:
- 缓冲区[strlen(buffer)-1]='\0';在客户端代码将被切掉 最后一个字符。应该是buffer[strlen(buffer)]='\0'; 相反李>
- 类型使用与sizeof()运算符的一致性很重要。
例如,在我的Mac上,sizeof(long)是8,而sizeof(uint32_t)是4。
这导致了缺乏
客户端和服务器之间的同步
// Assume maximum entry length is 255
// The buffer is 256 bytes long to accommodate the NULL-terminator.
// The terminator is important for the client as direntry delimiter.
char buffer[256];
// get the size of the directory
unsigned long size = htonl(dirSize());
int n = send(client_sock, &size, sizeof(size), 0);
if(n < 0) puts("can't send size to server");
DIR *d = opendir(".");
struct dirent *dir;
if (d)
{
while((dir = readdir(d))!= NULL)
{
memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
strcat(buffer, dir->d_name);
// Write up to 255 chars of direntry + the NULL-terminator.
n = send(client_sock, buffer, strlen(buffer) + 1, 0);
if(n < 0) puts("can't send entry to server");
}
closedir(d);
}
else{
puts("Error...could not get files from directory.");
}
char buffer[256];
/*
* We need this in case the beginning of a directory entry is in one buffer, but
* the end is in the next.
*/
char buf_1[256];
unsigned long size;
buf_1[0] = 0; // make sure strlen(buf_1) is 0.
int n = recv(sockfd, &size, sizeof(long), 0);// recieve the size of the directory
if(n < 0) puts("can't receive size from server");
size = ntohl(size);
while(size > 0){
memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
n = recv(sockfd, buffer, 255, 0); // keep last element of buffer as 0
if(n < 0) puts("can't receive entry from server");
int _start = 0;
if (strlen(buf_1)) // something left over from previously read buffer
{
// buf_1 contains beginning of an entry, buffer - the end
strcat(buf_1, buffer); // Assume there is a 0-terminator somewhere in buffer
printf("receiving: %s\n", buf_1); // buf_1 now has the entry, print it buf_1[0] = 0; // flag buf_1 as empty
size--; // we are one direntry down
_start += strlen(buffer) + 1; // move _start to char following 0-terminator
}
// Loop while _start is 0 - 254, the char at offset _start is not NULL,
// and there are still entries to retrieve.
while (_start < 255 && *(buffer + _start) && size > 0)
{
if (strlen( buffer + _start ) + _start >= 255) // no null terminator, need buf_1
{
strcpy(buf_1, buffer + _start); // copy unfinished entry to buf_1
// don't decrement size, we haven't extracted a full direntry.
break; // out of the inner while to read more from the socket.
}
else // we have a full direntry
{
printf("receiving: %s\n", buffer + _start); // print it
_start += strlen(buffer + _start) + 1; // move offset to next possible entry
size--; // one entry down
}
}
}
//假定最大条目长度为255
//缓冲区长度为256字节,以容纳空终止符。
//终止符作为direntry分隔符对客户端很重要。
字符缓冲区[256];
//获取目录的大小
无符号长大小=htonl(dirSize());
int n=send(client_sock,&size,sizeof(size),0);
如果(n<0)放入(“无法将大小发送到服务器”);
DIR*d=opendir(“.”);
结构方向*dir;
如果(d)
{
而((dir=readdir(d))!=NULL)
{
memset(&buffer[0],0,sizeof(buffer));//清除缓冲区
strcat(缓冲区,目录->数据单元名称);
//最多可写入255个字符的direntry+空终止符。
n=发送(客户端存储,缓冲区,strlen(缓冲区)+1,0);
如果(n<0)放入(“无法向服务器发送条目”);
}
closedir(d);
}
否则{
puts(“错误…无法从目录获取文件。”);
}
从套接字读取的客户端代码:
// Assume maximum entry length is 255
// The buffer is 256 bytes long to accommodate the NULL-terminator.
// The terminator is important for the client as direntry delimiter.
char buffer[256];
// get the size of the directory
unsigned long size = htonl(dirSize());
int n = send(client_sock, &size, sizeof(size), 0);
if(n < 0) puts("can't send size to server");
DIR *d = opendir(".");
struct dirent *dir;
if (d)
{
while((dir = readdir(d))!= NULL)
{
memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
strcat(buffer, dir->d_name);
// Write up to 255 chars of direntry + the NULL-terminator.
n = send(client_sock, buffer, strlen(buffer) + 1, 0);
if(n < 0) puts("can't send entry to server");
}
closedir(d);
}
else{
puts("Error...could not get files from directory.");
}
char buffer[256];
/*
* We need this in case the beginning of a directory entry is in one buffer, but
* the end is in the next.
*/
char buf_1[256];
unsigned long size;
buf_1[0] = 0; // make sure strlen(buf_1) is 0.
int n = recv(sockfd, &size, sizeof(long), 0);// recieve the size of the directory
if(n < 0) puts("can't receive size from server");
size = ntohl(size);
while(size > 0){
memset(&buffer[0], 0, sizeof(buffer)); // clear buffer
n = recv(sockfd, buffer, 255, 0); // keep last element of buffer as 0
if(n < 0) puts("can't receive entry from server");
int _start = 0;
if (strlen(buf_1)) // something left over from previously read buffer
{
// buf_1 contains beginning of an entry, buffer - the end
strcat(buf_1, buffer); // Assume there is a 0-terminator somewhere in buffer
printf("receiving: %s\n", buf_1); // buf_1 now has the entry, print it buf_1[0] = 0; // flag buf_1 as empty
size--; // we are one direntry down
_start += strlen(buffer) + 1; // move _start to char following 0-terminator
}
// Loop while _start is 0 - 254, the char at offset _start is not NULL,
// and there are still entries to retrieve.
while (_start < 255 && *(buffer + _start) && size > 0)
{
if (strlen( buffer + _start ) + _start >= 255) // no null terminator, need buf_1
{
strcpy(buf_1, buffer + _start); // copy unfinished entry to buf_1
// don't decrement size, we haven't extracted a full direntry.
break; // out of the inner while to read more from the socket.
}
else // we have a full direntry
{
printf("receiving: %s\n", buffer + _start); // print it
_start += strlen(buffer + _start) + 1; // move offset to next possible entry
size--; // one entry down
}
}
}
char缓冲区[256];
/*
*如果目录项的开头在一个缓冲区中,但是
*结局在下一个。
*/
char buf_1[256];
无符号长尺寸;
buf_1[0]=0;//确保strlen(buf_1)为0。
int n=recv(sockfd,&size,sizeof(long),0);//接收目录的大小
如果(n<0)放入(“无法从服务器接收大小”);
尺寸=ntohl(尺寸);
而(大小>0){
memset(&buffer[0],0,sizeof(buffer));//清除缓冲区
n=recv(sockfd,buffer,255,0);//将buffer的最后一个元素保留为0
如果(n<0)puts(“无法从服务器接收条目”);
int _start=0;
if(strlen(buf_1))//以前读取的缓冲区中剩余的内容
{
//buf_1包含条目的开头,buffer-结尾
strcat(buf_1,buffer);//假设缓冲区中某处有一个0-终止符
printf(“接收:%s\n,buf_1);//buf_1现在有了条目,打印它buf_1[0]=0;//将buf_1标记为