Client&Server 刷新缓冲区

Client&Server flushing buffer

我写了一个简单的代码Client/Server。代码在 运行s.

时执行以下操作

首先服务器等待客户端的消息,然后要求用户输入消息发送给客户端。当客户端第一次开始运行时,它要求用户输入一条消息发送给服务器,然后等待服务器的回复。

当我从客户端向服务器发送第一条消息时,程序工作正常,然后服务器要求我写一条消息发送给客户端,问题开始于此:

我输入消息并按回车键消息被发送到客户端,然后服务器收到相同的先前消息并提示我为客户端输入消息。从服务器或客户端发送的消息不会立即被读取和打印,除非我在服务器中键入另一条消息然后它显示从客户端发送的上一条消息。

服务器代码:

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

static void bail( const char* on_what ){
fputs(strerror(errno),stderr);
fputs(": ",stderr);
fputs(on_what,stderr);
fputc('\n',stderr);
exit(1);
}

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

int sockfd, bindfd, listenfd, acceptfd, writefd, readfd, len_inet;
struct sockaddr_in address_server, address_client;
char *server_address = "192.168.1.10";
char *server_portno = "9100";
char readBuffer[256], writeBuffer[256];

memset(&address_server, 0, sizeof address_server);
address_server.sin_family = AF_INET;
address_server.sin_port = htons(atoi(server_portno));
address_server.sin_addr.s_addr = inet_addr(server_address);
if(address_server.sin_addr.s_addr == INADDR_NONE)
    bail("bad address");

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if( sockfd == -1 )
    bail("socket()");
printf("socket created\n");

bindfd = bind(sockfd, (struct sockaddr *)&address_server, sizeof address_server);
if( bindfd == -1 )
    bail("bind()");
printf("bind done\n");

listenfd = listen(sockfd, 10);
if( listenfd == -1 )
    bail("listen()");
printf("Listening to Client\n");

len_inet = sizeof address_client;

acceptfd = accept(sockfd, (struct sockaddr *)&address_client, &len_inet);
if( acceptfd == -1 )
    bail("accept()");
    printf("Connection accepted\n");

while(1){

    printf("Reading from Client...\n");
    readfd = read(acceptfd, &readBuffer, sizeof readBuffer-1);
    if( readfd == -1 )
        bail("read()");

    printf("Message from Client: %s\n", readBuffer);

    printf("Enter a message to send to Client:\n");
    fgets(writeBuffer, 255, stdin);
    writefd = write(acceptfd, writeBuffer, sizeof writeBuffer);
    if( writefd == -1 )
        bail("write()");
}

close(acceptfd);
printf("Closing Connection\n");

return (EXIT_SUCCESS);
}

客户代码:

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

void static bail( const char* on_what ){
fputs(strerror(errno),stderr);
    fputs(": ",stderr);
    fputs(on_what,stderr);
    fputc('\n',stderr);
    exit(1);
}

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

int sockfd, connectfd, readfd, writefd, len_inet;
struct sockaddr_in address_server;
char *server_address = "192.168.1.240";
char *server_portno = "9100";
char readBuffer[256], writeBuffer[256];

memset(&address_server, 0, sizeof address_server);
address_server.sin_family = AF_INET;
address_server.sin_port = htons(atoi(server_portno));
address_server.sin_addr.s_addr = inet_addr(server_address);
if( address_server.sin_addr.s_addr == INADDR_NONE)
    bail("bad address");

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if( sockfd == -1 )
    bail("socket()");
printf("socket created\n");

len_inet = sizeof address_server;

connectfd = connect(sockfd, (struct sockaddr *)&address_server, len_inet);
if( connectfd == -1 )
    bail("connect()");
printf("Connected\n");

while(1){
    printf("Please enter a message to send to the Server: \n");
    fgets(writeBuffer, 255, stdin);
    writefd = write(sockfd, writeBuffer, sizeof writeBuffer);
    if( writefd == -1 )
        bail("write(2)");

    printf("Waiting for a message from the server\n");
    readfd = read(sockfd, &readBuffer, sizeof readBuffer-1);
    if( readfd == -1 )
        bail("read(2)");
    readBuffer[readfd] = 0;
    printf("Message from the server: %s\n", readBuffer);
}

close(sockfd);
printf("Connection Closed\n");

return 0;
}

你的代码有几个问题,服务器:

printf("Reading from Client...\n");
readfd = read(acceptfd, &readBuffer, sizeof readBuffer-1);
if( readfd == -1 )
    bail("read()");

readBuffer是一个数组,如果传给一个函数,它已经是一个指向它第一个元素的指针,所以你不能使用&readBuffer,只能使用readBuffer,然后读取之后,你需要终止缓冲区,就像C中的字符串只是空终止字符数组:

printf("Reading from Client...\n");
readfd = read(acceptfd, readBuffer, sizeof readBuffer-1);
if( readfd == -1 )
    bail("read()");
readBuffer[readfd] = '[=11=]';

fgets 不会让您知道它读取了多少个字符到缓冲区中,因此您不能只将整个缓冲区写入套接字,而是写入字符串,使用 strlen 来确定您需要写入的字符串的大小:

writefd = write(acceptfd, writeBuffer, strlen(writeBuffer));

在客户端中,与缓冲区相同的问题:

writefd = write(sockfd, writeBuffer, strlen(writeBuffer));
...
readfd = read(sockfd, readBuffer, sizeof readBuffer-1);
readBuffer[readfd] = '[=13=]';