此程序的服务器会保留一系列故障单号码以及它们是否可用。
客户要求从服务器购买或退票。
我当然不太了解select fx。根据我的判断,您可以将套接字的文件描述符加载到结构中,并选择()检查这些fds是否已准备好读取或写入。这是对的吗?
我需要使用select函数来读取来自2个不同客户端的请求。我认为除了服务器不会在客户端的第二个请求中读取之外,我的工作大部分都在工作。服务器读入第一个客户端请求,处理它并响应,然后挂起,等待下一个请求。
感谢您的帮助,请随时给我任何指示!
服务器代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <stdlib.h>
void error(const char *message);
void generateTickets(int ticketArray[][2]);
void parseBuffer(char buffer[], char* request[]);
int sellTicket(int ticketArray[][2], int* refPtr);
int returnTicket(int returnTicketNumber, int ticketArray[][2], int* refPtr);
void printTickets(int ticketArray[][2]);
int main(int argc, char *argv[])
{
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
int svrSocketFd;//file descriptor for the server side
int cliSocketFd;//file descriptor fot the client side
int portNum;//port number
int readWrite;//holds the return values of the read/write functions
socklen_t clientLength;//holds the size in bytes of the sockaddr client struct
char buffer[256];//buffer for reading and writing
struct sockaddr_in serverAddress;//server struct
struct sockaddr_in clientAddress;//client struct
fd_set readfds;
struct timeval timeout={0,0};
int selectReturn;
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
int ticketArray[25][2], returnTicketNumber;//holds ticket nums and whether or not they are avalible (0/1)
int ticketsAvalible = 25;//number of tickets avalible
int *refPtr = &ticketsAvalible;
char *request[2];//stores parsed client requests
int i, stringComp, soldTicketNum, clientCheck;
srand(time(0));//seed random number generator
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
generateTickets(ticketArray);
printTickets(ticketArray);
//check if the correct number of arguments was provided
if(argc < 2)
{
error("ERROR: Port number required\n");
}
svrSocketFd = socket(AF_INET, SOCK_STREAM, 0);//creates a socket for the server
//check that the socket was created
if(svrSocketFd < 0)
{
error("ERROR: Server socket not created\n");
}
bzero((char *) &serverAddress, sizeof(serverAddress));//not really sure what this does
portNum = atoi(argv[1]);//convert passed in port from char to int
//set the member variables of the server sockaddr struct
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = INADDR_ANY;
serverAddress.sin_port = htons(portNum);
int on=1;
setsockopt(svrSocketFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
//bind the socket to the server struct?
if(bind(svrSocketFd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
{
error("ERROR: Unable to bind socket");
}
listen(svrSocketFd, 5);
while(1)
{
do
{
FD_ZERO(&readfds);
FD_SET(svrSocketFd, &readfds);
selectReturn = select(svrSocketFd + 1, &readfds, NULL, NULL, &timeout);
if(selectReturn > 0)
{
clientLength = sizeof(clientAddress);//returns the size in bytes of the client struct
cliSocketFd = accept(svrSocketFd, (struct sockaddr *) &clientAddress, &clientLength);
bzero(buffer, 256);//zeros out the buffer
readWrite = read(cliSocketFd, buffer, 256);//read data in from the client)
printf("SERVER IN buffer = %s\n", buffer);
parseBuffer(buffer, request);//parse buffer and separate into the request array
stringComp = strcmp(request[0], "BUY");
if(stringComp == 0)//buy request
{
soldTicketNum = sellTicket(ticketArray, refPtr);
bzero(buffer, 256);//zeros out the buffer
sprintf(buffer, "%d", soldTicketNum);
printf("SERVER OUT buffer = %s\n", buffer);
readWrite = write(cliSocketFd, buffer, strlen(buffer));
}
stringComp = strcmp(request[0], "RETURN");
if(stringComp == 0)
{
returnTicketNumber = atoi(request[1]);
if(returnTicket(returnTicketNumber, ticketArray, refPtr))
{
printf("[SERVER]: RETURNED %d\n", returnTicketNumber);
}
else
{
printf("[SERVER]: RETURNED %d failed\n", returnTicketNumber);
}
}
}
}while(selectReturn > 0);
}
printTickets(ticketArray);
//close the client and server sockets
close(cliSocketFd);
close(svrSocketFd);
return 0;
}
void error(const char *message)
{
perror(message);
exit(1);
}
void generateTickets(int ticketArray[][2])
{
int i;
for(i = 0; i < 25; i++)
{
ticketArray[i][0] = (rand () % 40000 + 10000);
ticketArray[i][1] = 1;
}
}
void parseBuffer(char buffer[], char* request[])
{
char *token;
int i = 0;
token = strtok(buffer, " ");
while(token != NULL)
{
request[i] = token;
i++;
token = strtok(NULL, " ");
}
}
int sellTicket(int ticketArray[][2], int* refPtr)
{
int i = 0;
if(*refPtr == 0)
{
printf("[SERVER]: No tickets avalible\n");
return -1;
}
else
{
//searches for the first avalible ticket and returns the ticket number
while(ticketArray[i][1] == 0)
{
i++;
}
(*refPtr)--;//decrement ticketsAvalible
ticketArray[i][1] = 0;//set ticket as sold (0)
return ticketArray[i][0];
}
}
int returnTicket(int returnTicketNumber, int ticketArray[][2], int* refPtr)
{
int i = 0;
while(ticketArray[i][0] != returnTicketNumber && i < 25)
{
i++;
if(ticketArray[i][0] == returnTicketNumber && ticketArray[i][1] == 0)
{
ticketArray[i][1] = 1;
(*refPtr)++;
return 1;
}
}
return 0;
}
void printTickets(int ticketArray[][2])
{
int i = 0;
while(i < 25)
{
if(ticketArray[i][1] == 0)
{
printf("[Ticket # %d] %d : SOLD\n", i, ticketArray[i][0]);
}
else
{
printf("[Ticket # %d] %d : AVAIL\n", i, ticketArray[i][0]);
}
i++;
}
}
客户代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <stdlib.h>
void error(const char *message);
int buyOrReturn();
void buyTicket(char buffer[], int ticketArray[], int* refPtr);
void returnTicket(char buffer[], int ticketArray[], int* refPtr);
void printTickets(int ticketArray[]);
int main(int argc, char *argv[])
{
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
int cliSocketFd;//hold the file descriptor for the socket
int portNum;//port number
int readWrite;//return values for read/write functions
struct sockaddr_in serverAddress;//server struct containing the address of the server
struct hostent *server;//defines a host computer on the internet
char buffer[256];//buffer for reading and writing
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
int requestNumber = 20;
int ticketArray[20];//holds ticket nums
int ticketsAvalible = 0;//number of tickets avalible
int *refPtr = &ticketsAvalible;
int randomNumber;//stores a random number of either a ticket number or decision to buy/sell
int i;
srand(time(0));//seed the random number generator
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
for(i = 0; i < 20; i++)
{
ticketArray[i] = 0;
}
printTickets(ticketArray);
//check for the correct number of arguments
if(argc < 3)
{
error("ERROR: Need arguments - \"hostname\" \"port number\"\n");
}
portNum = atoi(argv[2]);//convertargv string into an int
cliSocketFd = socket(AF_INET, SOCK_STREAM, 0);//open a socket
//test is the socket was opened successfully
if(cliSocketFd < 0)
{
error("ERROR: Socket did not open\n");
}
server = gethostbyname(argv[1]);//returns a pointer to a host
//check is the system successfully located the host
if(server == NULL)
{
error("ERROR: No host found\n");
}
bzero((char *) &serverAddress, sizeof(serverAddress));//initializes serverAddress to zero
//set the fields in serverAddress
serverAddress.sin_family = AF_INET;
bcopy((char *) server->h_addr, (char *) &serverAddress.sin_addr.s_addr, server->h_length);
serverAddress.sin_port = htons(portNum);
//establish and check a connection with the server
if(connect(cliSocketFd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
{
error("ERROR: Could not connect to the server\n");
}
while(requestNumber != 0)
{
printf("REQUEST#: %d\n", requestNumber);
bzero(buffer, 256);//clears the buffer
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
if(buyOrReturn())//1 buys, 0 returns
{
printf("CLIENT: sending buy request\n");
strcpy(buffer, "BUY ");
printf("CLIENT OUT buffer = %s\n", buffer);
//RW
readWrite = write(cliSocketFd, buffer, strlen(buffer));//send message to the server
//check if message was not sent
if(readWrite < 0)
{
error("ERROR: Message was not sent\n");
}
bzero(buffer, 256);//clears the buffer
//RW
readWrite = read(cliSocketFd, buffer, 256);
printf("CLIENT IN buffer = %s\n", buffer);
buyTicket(buffer, ticketArray, refPtr);
}
else
{
printf("CLIENT: sending return request\n");
returnTicket(buffer, ticketArray, refPtr);
printf("CLIENT buffer = %s\n", buffer);
//RW
readWrite = write(cliSocketFd, buffer, strlen(buffer));
}
requestNumber--;
}
printTickets(ticketArray);
close(cliSocketFd);//close the socket
return 0;
}
void error(const char *message)
{
perror(message);
exit(1);
}
int buyOrReturn()
{
if((rand() % 4) < 3)
{
return 1;//buy
}
else
{
return 0;//return
}
}
void buyTicket(char buffer[], int ticketArray[], int* refPtr)
{
int stringCmp = strcmp(buffer, "-1");
if(stringCmp != 0)
{
ticketArray[*refPtr] = atoi(buffer);
(*refPtr)++;
return;
}
else
{
return;
}
}
void returnTicket(char buffer[], int ticketArray[], int* refPtr)
{
int randomTicketNumber;
char returnTicketNumber[6];
if(*refPtr == 0)
{
randomTicketNumber = (rand () % 50000 + 49999);
sprintf(returnTicketNumber, "%d", randomTicketNumber);
strcpy(buffer, "RETURN ");
strcat(buffer, returnTicketNumber);
printf("CLIENT buffer = %s\n", buffer);
return;
}
else
{
strcpy(buffer, "RETURN ");
sprintf(returnTicketNumber, "%d", ticketArray[*refPtr]);
strcat(buffer, returnTicketNumber);
(*refPtr)--;//it is assumed that the ticket is valid and returned without error
return;
}
}
void printTickets(int ticketArray[])
{
int i;
for(i = 0; i < 20; i++)
{
printf("[Ticket # %d] %d\n", i, ticketArray[i]);
}
}