gpt4 book ai didi

c - recv 不会将整个消息保存在缓冲区中

转载 作者:太空宇宙 更新时间:2023-11-04 06:04:21 26 4
gpt4 key购买 nike

我使用 send 和 recv 在客户端和服务器之间传递消息。在服务器端,当我在缓冲区 fname 上收到消息时,保存的消息不是从客户端发送的完整消息

服务器

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h> /*For Sockets*/
#include <sys/socket.h> /*For Sockets*/
#include <netdb.h> /*For gethostbyaddr()*/
#include <netinet/in.h> /*For internet sockets*/
#include <dirent.h>


/*Function for creating the lof file of Server*/

void log_event (char *message,char *filename)
{

FILE *file;
char *log_this;

time_t system_time; //Get the system time
time(&system_time);

log_this=strcat(ctime(&system_time),message); //Create the message to log

/*Check for filename and log as appropiate*/

if (filename!=NULL)
{
file = fopen(filename,"a+");
fprintf(file,"%s",log_this); /*writes the message*/
fclose(file); /*done!*/
}
else
{
file = fopen("ftp_tracelog.txt","a+");
fprintf(file,"%s",log_this); /*writes the message*/
fclose(file); /*done!*/
}

}

int main (int argc,char *argv[])
{

/*DECLERATIONS*/

char *filename;
char message [1024];
char *temp;
char temp_2[1024];
char fname[128];
char request[1024];
char op[1000];
char command[5];
FILE *fp;
DIR *dp;
char list[1024];
int port,sock,newsock,serverlen,clientlen,fname_len,recvMsgSize,i;
char buf[256];

struct sockaddr_in server,client;
struct sockaddr *serverptr, *clientptr;
struct hostent *rem;
struct dirent *ep;

/*END OF DECLERATIONS*/

/*Check for required arguments and get them as appropiate*/

if (argc < 2) {
/* Check if server's port number is given */
printf("Please give the port number!!!\n");
exit(1);
}

/*if server's port number is given and filename for log is given*/

if(argc>2){
filename=argv[1];
port=atoi(argv[2]);
}

/*If only port is given*/

if (argc==2){
port=atoi(argv[1]);
filename=NULL;
}
temp="--Server is Starting!!--";
sprintf(message,"%s\n",temp);
log_event(message,filename);

/* Create socket */

if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{perror("socket"); exit(1); }

server.sin_family = PF_INET; /* Internet domain */
server.sin_addr.s_addr = htonl(INADDR_ANY); /* My Internet address */
server.sin_port = htons(port); /* The given port */
serverptr = (struct sockaddr *) &server;
serverlen = sizeof (server);

/* Bind socket to address */

if (bind(sock, serverptr, serverlen) < 0) {
perror("bind"); exit(1); }

/* Listen for connections */

if (listen(sock, 40) < 0) { /* 5 max. requests in queue */
perror("listen"); exit(1); }

temp="---Listening for connections to port";
sprintf(temp_2,"%d----",port);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);

/*Accepting Connecttion*/

while(1) {
clientptr = (struct sockaddr *) &client;
clientlen = sizeof(client);
/* Accept connection */
if ((newsock = accept(sock, clientptr, &clientlen)) < 0) {
perror("accept"); exit(1); }
/* Find client's address */
if ((rem = gethostbyaddr((char *) &client.sin_addr.s_addr,
sizeof (client.sin_addr.s_addr), client.sin_family)) == NULL) {
perror("gethostbyaddr"); exit(1);
}

temp="----Accepted connection from ";
sprintf(temp_2,"%s----", rem -> h_name);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);

/* Create child for serving the client */
switch (fork()) {

case -1:
perror("fork"); exit(1);

case 0: /* Child process */
do{
/* Receive message from client */
if ((recvMsgSize = recv(newsock,request,sizeof(request),0))< 0)
perror("recv() failed");
//printf("%s\n",request);

strncpy(command,request,4);
printf("%s\n",command);
/*IF YOU ARE GOING TO EXECUTE AN LS COMMAND*/

if (strcmp(command,"ls")==0)
{
dp = opendir ("./");

if (dp != NULL)
{ /*LOG LS REQUEST*/

temp="--Client ";
sprintf(temp_2,"%s requested ls -------",rem -> h_name);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);

/*SEND ALL DIRECTORY LISTING*/

while (ep = readdir (dp))
{
strcpy(list,ep->d_name);
//printf("sending:%s\n",list);
if (send(newsock,list,sizeof(list), 0)!= sizeof(list))
perror("send() sent a different number of bytes than expected");
}
//IF DIRECORY IS FINISHED SEND A LAST MESSAGE FOR ENDING

(void) closedir (dp);
if (send(newsock,"end",sizeof("end"), 0)!= sizeof("end"))
perror("send() sent a different number of bytes than expected");
}
else
perror ("Couldn't open the directory");
}
/*IF THE COMMAND IS PUT*/

if (strcmp(command,"put")==0)
{
printf("execute put!!\n");

bzero(fname, sizeof fname); /* Initialize buffer */

if ((recvMsgSize = recv(newsock,fname,128, MSG_WAITALL)) < 0)
perror("recv() failed");

printf("%s!!!!\n",fname);

}
}while (strcmp(request,"end")!=0); //run until client sents end request

/*LOG EXIT OF CLIENT*/

temp="--Client";
sprintf(temp_2,"%s is disconnected---",rem -> h_name);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);

close(newsock); /* Close socket */
exit(0);
} /* end of switch */
} /* end of while(1) */


}

客户

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

int main (int argc,char *argv[])
{

int port, sock, serverlen,recvMsgSize;
int fname_len,msg_len,request_len;
char buf[256];
char fname[128];
char request[1204];
char list[1024];
char msg[512];
char op[1000];
char temp[5];
char *temp3;
FILE *fp;


struct sockaddr_in server;
struct sockaddr *serverptr;
struct hostent *rem;

temp3="put";

/* Are server's host name and port number given? */
if (argc < 3) {
printf("Please give host name and port number\n"); exit(1);

}

/* Create socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}

/* Find server address */
if ((rem = gethostbyname(argv[1])) == NULL) {
herror("gethostbyname"); exit(1);
}

/* Convert port number to integer */
port = atoi(argv[2]);

/* Internet domain */
server.sin_family = PF_INET;
bcopy((char *) rem -> h_addr, (char *) &server.sin_addr,
rem -> h_length);

/*Server's Internet address and port*/
server.sin_port = htons(port);
serverptr = (struct sockaddr *) &server;
serverlen = sizeof(server);


if (connect(sock, serverptr, serverlen) < 0) { /* Request connection */
perror("connect");
exit(1); }

printf("Requested connection to host %s port %d\n", argv[1], port);



do{
printf("Please enter request\n:");
scanf("%s",request);

request_len=sizeof(request);

/* Send the string to the server */
if (send(sock,request,request_len, 0)!= request_len)
perror("send() sent a different number of bytes than expected");

strncpy(temp,request,4);
printf("%s\n",temp);

if(strcmp(temp,"ls")==0)
{
sprintf(list,"");

/*Recieve from server*/
while(strcmp(list,"end")!=0){

if ((recvMsgSize = recv(sock,list,sizeof(list),0))< 0)
perror("recv() failed");

if(strcmp(list,"end")!=0){
printf("%s\n",list);
}
}
}

/*Command for put*/
if(strcmp(request,temp)==0)
{
printf("Please enter filename:\n");
scanf("%s",fname);

if (send(sock,fname,128, MSG_DONTWAIT)!= 128)
perror("send() sent a different number of bytes than expected");

}
}while (strcmp(request,"end")!=0);
close(sock); /* Close socket */
exit(0);
}

最佳答案

当您调用 recv 时,您需要检查接收到的字节数。如果小于您要求的,则需要再次调用 recv,并将其添加到先前接收的缓冲区的末尾。可能发生的情况是,当您第一次调用 recv 时,只有部分消息到达。

char buf[N];
char* p = buf;
ssize_t bytesRemaining = N;
while (bytesRemaining) {
ssize_t recvd;
recvd = recv(sock, p, bytesRemaining, 0);
bytesRemaining -= recvd; // keep track of bytes left
p += recvd; // advance buffer pointer
}

关于c - recv 不会将整个消息保存在缓冲区中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13223821/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com