我目前无法从服务器读取多个值。 这是一个客户端/服务器程序。 用户应该键入客户端中的国家/地区名称,然后服务器将返回该国家的资本及其货币。 我成功键入了第一个输入示例中国,服务器返回正确的数据。但是,当我把后来的价值作为新加坡的时候。他们一无所获。希望你们能告诉我代码有什么问题。服务器应该返回键入的国家的资本和货币。
以下是我的服务器和客户端代码。对不起,他们有点长,但我觉得更好,我给你们全貌了
server.c
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h> /* for sockaddr_un struct */
#include <string.h>
#include "country.h"
#define DEFAULT_PROTOCOL 0
/* POSIX renames "Unix domain" as "local IPC."
Not all systems define AF_LOCAL and PF_LOCAL (yet). */
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#ifndef PF_LOCAL
#define PF_LOCAL PF_UNIX
#endif
/****************************************************************/
int main ()
{
int serverFd, clientFd, serverLen, clientLen;
struct sockaddr_un serverAddress;/* Server address */
struct sockaddr_un clientAddress; /* Client address */
struct sockaddr* serverSockAddrPtr; /* Ptr to server address */
struct sockaddr* clientSockAddrPtr; /* Ptr to client address */
/* Ignore death-of-child signals to prevent zombies */
signal (SIGCHLD, SIG_IGN);
serverSockAddrPtr = (struct sockaddr*) &serverAddress;
serverLen = sizeof (serverAddress);
clientSockAddrPtr = (struct sockaddr*) &clientAddress;
clientLen = sizeof (clientAddress);
/* Create a socket, bidirectional, default protocol */
serverFd = socket (AF_LOCAL, SOCK_STREAM, DEFAULT_PROTOCOL);
serverAddress.sun_family = AF_LOCAL; /* Set domain type */
strcpy (serverAddress.sun_path, "country"); /* Set name */
unlink ("country"); /* Remove file if it already exists */
bind (serverFd, serverSockAddrPtr, serverLen); /* Create file */
listen (serverFd, 5); /* Maximum pending connection length */
printf ("%s \n", "Starting Country Server");
printf ("%s \n", " ");
while (1) /* Loop forever */
{
/* Accept a client connection */
clientFd = accept (serverFd, clientSockAddrPtr, &clientLen);
if (fork () == 0) /* Create child to send recipe */
{
//writeCountryData (clientFd); /* Send the recipe */
while(1)
{
readCountry (clientFd);
close (clientFd); /* Close the socket */
exit (/* EXIT_SUCCESS */ 0); /* Terminate */
}
else
close (clientFd); /* Close the client descriptor */
}
return 0;
}
/****************************************************************/
readCountry (int fd)
{
readData();
char capital[100]="", currencyCode[100]="", *p;
char userInput[200];
read(fd, userInput, 200);
if ((p = strchr(userInput, '\n')) != NULL) /* to remove the [enter] from userinput */
*p = '\0';
strcat(capital,userInput) ;
strcat(capital," Capital : ") ;
strcat(capital,getCapital (userInput));
write (fd, capital, strlen (capital) + 1);
strcat(currencyCode,userInput) ;
strcat(currencyCode," Currency Code : ") ;
strcat(currencyCode,getCurrencyCode (userInput));
write (fd, currencyCode, strlen (currencyCode) + 1);
}
readLine (int fd, char* str)
{
int n;
do /* Read characters until NULL or end-of-input */
{
// ssize_t read (int fd, void *buf, size_t count);
// if successful, read will:
// a) stores data read into 'buf', and
// b) returns the no. of bytes read
// read returns zero if it reaches end-of-input
n = read (fd, str, 1); /* Read one character */
}
while (n > 0 && *str++ != 0);
return (n > 0); /* Return false if end-of-input */
}
}
client.c
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h> /* for sockaddr_un struct*/
#define DEFAULT_PROTOCOL 0
/* POSIX renames "Unix domain" as "local IPC."
Not all systems define AF_LOCAL and PF_LOCAL (yet). */
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#ifndef PF_LOCAL
#define PF_LOCAL PF_UNIX
#endif
/****************************************************************/
main ()
{
int clientFd, serverLen, result;
struct sockaddr_un serverAddress;
struct sockaddr* serverSockAddrPtr;
serverSockAddrPtr = (struct sockaddr*) &serverAddress;
serverLen = sizeof (serverAddress);
/* Create a socket, bidirectional, default protocol */
clientFd = socket (AF_LOCAL, SOCK_STREAM, DEFAULT_PROTOCOL);
serverAddress.sun_family = AF_LOCAL; /* Server domain */
strcpy (serverAddress.sun_path, "country"); /* Server name */
do /* Loop until a connection is made with the server */
{
result = connect (clientFd, serverSockAddrPtr, serverLen);
if (result == -1) sleep (1); /* Wait and then try again */
}
while (result == -1);
while (1)
{
char country[300];
printf("To end program, type 'end' \n");
printf("Please enter country name >");
fgets(country,sizeof(country),stdin);
if (strcmp(country,"end\n") == 0)
{
printf("Thank you for using country services\n");
break;
}
else
write(clientFd,country,strlen(country));
readCountry(clientFd);
close(clientFd);
}
/* Read the recipe */
/* Close the socket */
exit (/* EXIT_SUCCESS */ 0); /* Done */
}
/**************************************************************/
readCountry(int fd)
{
char str[300];
while (readLine (fd, str)) /* Read lines until end-of-input */
printf ("%s\n", str); /* Echo line from socket */
}
/**************************************************************/
/* Read a single NULL-terminated line */
readLine (int fd, char* str)
{
int n;
do /* Read characters until NULL or end-of-input */
{
// ssize_t read (int fd, void *buf, size_t count);
// if successful, read will:
// a) stores data read into 'buf', and
// b) returns the no. of bytes read
// read returns zero if it reaches end-of-input
n = read (fd, str, 1); /* Read one character */
}
while (n > 0 && *str++ != 0);
return (n > 0); /* Return false if end-of-input */
}
writeUserInput(int fd)
{
char text[20];
printf("To end program, type 'end' \n\n\n");
printf("Please enter Country > ");
fgets (text, sizeof(text), stdin);
write (fd, text, strlen (text) + 1);
}
答案 0 :(得分:3)
服务器评论 您需要每次都设置套接字大小。
/* Accept a client connection */
clientLen = sizeof (clientAddress); // this line was missing
lientFd = accept (serverFd, clientSockAddrPtr, &clientLen);
事实上,如果你声明变量使用它们,那么RAII会消除这类问题。
我刚刚注意到这是C而不是C ++,所以忘记了RAII评论,但确实需要设置大小。
您应该使用sizeof:
char userInput[200];
read(fd, userInput, 200);
strncat应该用在:
char capital[100]="", currencyCode[100]="", *p;
//...
strcat(capital,userInput) ;
strcat(capital," Capital : ") ;
和currencyCode相同。
你实际上并不需要fork(),它可以在一个线程/进程中完成。
Client Comments
代码是:
connect to server
while (true)
get input
send request
read reply
close connection to server