0

我已经使用 C 中的 Socket 编程修改了一个简单的聊天程序代码。我的问题是我必须在服务器或客户端输入两行才能接收另一行。我已经上传了一张图片来解释更多。任何帮助表示赞赏

SERVER
#include <stdio.h>
#include <sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<strings.h>
#include<unistd.h>
#define SERVER_TCP_PORT 3000
#define BUFLEN 256

int main (int argc,char **argv)
{
    int n,bytes_to_read;
    int sd,new_sd,client_len,port;
    struct sockaddr_in server,client;
    char *bp,buf[BUFLEN];

    switch (argc) {
        case 1:
            port = SERVER_TCP_PORT;
            break;
        case 2:
            port = atoi (argv[1]);
            break;
        default:
            fprintf (stderr,"Usage: %s[port]\n",argv[0]);
            exit(1);
            }
    /*Create a system socket */

        if ((sd = socket(AF_INET,SOCK_STREAM,0))==-1){
            fprintf(stderr,"Can't create a socket\n");
            exit(1);
            }

    /*Bind an address to the socket*/

    bzero ((char*)&server,sizeof(struct sockaddr_in));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    if(bind(sd,(struct sockaddr *)&server,sizeof(server))==-1){
        fprintf(stderr,"can't bind name to socket\n");
        exit(1);
    }
    /*queue up to 5 connect requests*/

    listen(sd,5);
    while(1){
        client_len = sizeof(client);
    if((new_sd = accept(sd,(struct sockaddr *)&client,&client_len))==-1){
        fprintf(stderr,"can't accept client \n");
        exit(1);
        }

if(fork())
{
printf("\n Server listening to clients on port 2000");
printf("\n Server got request from%s",inet_ntoa(client.sin_addr));
printf("\n SEND DATA<q or Q to quit> :%s",buf);
scanf("%s",buf);
while((strcmp(buf,"q")!=0)&&(strcmp(buf,"Q")!=0))
{
send(new_sd,buf,30,0);
scanf("%s",buf);

}
send(new_sd,"q",5,0);
}
else{
n = recv(new_sd,buf,30,0);
while((strcmp(buf,"q")!=0)&&(strcmp(buf,"Q")!=0))
{
printf("\nRECEIVED DATA =%s",buf);
n = recv(new_sd,buf,30,0);

}
printf("\n Bye");
send(new_sd,"EOF",4,0);
close(sd);
close(new_sd);
}
}
return 0;
} 



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

#define SERVER_TCP_PORT 3000
#define BUFLEN 256
int main(int argc,char **argv)
{

int n,bytes_to_read;
int sd,port;
struct hostent *hp;
struct sockaddr_in server;
char *host,*bp,rbuf[BUFLEN],sbuf[BUFLEN];
switch(argc) {
    case 2:
        host = argv[1];
        port = SERVER_TCP_PORT;
        break;
    case 3:
        host = argv[1];
        port = atoi(argv[2]);
        break;
    default:
        fprintf(stderr,"Usage: %s host[port] \n",argv[0]);
        exit(1);
        }

/*Create a stream socket*/

if ((sd=socket(AF_INET,SOCK_STREAM,0))==-1){
    fprintf(stderr,"Can't create a socket\n");
    exit(1);
    }
bzero ((char *)&server,sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(port);
if((hp = gethostbyname(host))==NULL){
    fprintf (stderr,"Can't get server's address\n");
    exit(1);
    }
bcopy(hp->h_addr,(char *)&server.sin_addr,hp->h_length);
/*connecting to the server*/

if (connect (sd,(struct sockaddr *)&server,sizeof(server))==-1){
    fprintf(stderr,"Can't connect \n");
    exit(1);
    }
printf("Connected:server's address is %s\n",hp->h_name);

if(fork())
{
bzero(rbuf,30);
printf("\n SEND DATA<q or Q to quit> :%s",rbuf);
scanf("%s",rbuf);
while((strcmp(rbuf,"q")!=0)&&(strcmp(rbuf,"Q")!=0))
{
send(sd,rbuf,30,0);
scanf("%s",rbuf);

} 
send(sd,"q",5,0);
}

else{
n = recv(sd,rbuf,30,0);
while((strcmp(rbuf,"q")!=0)&&(strcmp(rbuf,"Q")!=0))
{
printf("\nRECEIVED DATA =%s",rbuf);
n = recv(sd,rbuf,30,0);

}
printf("\n Bye");
send(sd,"EOF",4,0);
close(sd);
}

return 0;
}  
4

3 回答 3

1

As far as I understand, you want to read lines one by one. however, recv() function does not deliver the messages to you one by one since it only reads certain amount of data from the message stream. In order to differentiate between messages, there are two ways.

First, you send a fixed-size message -in this case 30 bytes- and always read 30 bytes from the otherside of the network.

Second, you encapsulate your data with a structure that contains the data length so as to provide various-sized messages. This method is better, because if you want to send -let's say- 1024-byte long string, otherside will know it and read 1024 bytes accordingly.

于 2012-10-22T09:51:44.303 回答
1

您每次只发送/接收 30 个字节。也许应该是BUFLEN?更好的是,在消息的前面有一个固定大小的块,其中包括strlen消息的。

例如:

int size = htonl(strlen(buf)+1);
send(new_sd, size, sizeof(size), 0);
send(new_sd, buf, size, 0); 

客户:

int size;
recv(sd, size, sizeof(size),0);
size = ntohl(size);
recv(sd, buf, size, 0);

为清楚起见,省略了错误检查。

于 2012-10-22T09:19:58.687 回答
0

我一定是做错了什么,我已将大小添加到标题消息中,现在没有从客户端和服务器接收任何数据。我正确使用它。这是我插入大小的代码的一部分。

服务器

if(fork())
{
printf("\n Server listening to clients on port 2000");
printf("\n Server got request from%s",inet_ntoa(client.sin_addr));
bzero(buf,256);
printf("\n SEND DATA<q or Q to quit> :%s",buf);
scanf("%s",buf);
while((strcmp(buf,"q")!=0)&&(strcmp(buf,"Q")!=0))
{
int size = htonl(strlen(buf)+1);
send(new_sd,size,sizeof(size),0);
send(new_sd,buf,size,0);
scanf("%s",buf);

}
send(new_sd,"q",5,0);
}
else{

int size;
recv(new_sd,size,sizeof(size),0);
size=ntohl(size);
n=recv(new_sd,buf,size,0);
while((strcmp(buf,"q")!=0)&&(strcmp(buf,"Q")!=0))
{
printf("\nRECEIVED DATA =%s",buf);
n = recv(new_sd,buf,size,0);
}
printf("\n Bye");
send(new_sd,"EOF",BUFLEN,0);
close(sd);
close(new_sd);
}
}
return 0;
} 

客户

if(fork())
{
printf("\n SEND DATA<q or Q to quit> :%s",rbuf);
scanf("%s",rbuf);
while((strcmp(rbuf,"q")!=0)&&(strcmp(rbuf,"Q")!=0))
{
int size = htonl(strlen(sbuf)+1);
send(sd,size,sizeof(size),0);
send(sd,sbuf,size,0);
scanf("%s",sbuf);

} 
send(sd,"q",5,0);
}

else{
int size;
recv(sd,size,sizeof(size),0);
size = ntohl(size);
recv(sd,rbuf,size,0);
while((strcmp(rbuf,"q")!=0)&&(strcmp(rbuf,"Q")!=0))
{
printf("\nRECEIVED DATA =%s",rbuf);
//n = recv(sd,rbuf,bytes_to_read,0);

}
printf("\n Bye");
send(sd,"EOF",4,0);
close(sd);
}

return 0;
}  
于 2012-10-22T18:49:43.467 回答