gpt4 book ai didi

c - 错误读取失败: Success (simple multi-threaded server) c programming

转载 作者:行者123 更新时间:2023-11-30 15:14:11 26 4
gpt4 key购买 nike

正如标题所述,我收到一个奇怪的错误“错误读取失败:服务器端成功”和“错误连接:传输端点已连接”

我正在尝试制作一个简单的多线程银行服务器,客户端可以连接到该服务器并管理帐户。

我是新手,这是我第一次使用套接字和线程,所以请放轻松。我很抱歉代码没有完全整洁,但这仍然是一项正在进行的工作。这是服务器

    /*
* makeSocket function creates, initializes, and binds a socket on a given port
*
* revieces a void* pointing to a port number
*
* returns socket descriptor
*/
int makeSocket(void* port)
{
//uint16_t portNum = *(uint16_t*) port;
int sock;
struct sockaddr_in name;

// Create the socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
error("ERROR opening socket");

// bzero may also work here
memset(&name, 0, sizeof(struct sockaddr_in));


/*Prepare the sockaddr_in struct
*/
name.sin_family = AF_INET;
name.sin_port = htons(PORT_NUM); // htons change the bit format of a number to network type
name.sin_addr.s_addr = INADDR_ANY;

// Bind socket
if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0)
error("ERROR on binding");

printf(" socket made ");
return sock;
}

/*
* prompt function writes bank prompt to a given socket
*
* reciieves a socket descriptor as an int
*
* does not return anything
*/
void prompt(int sock)
{
char *message, *opt1, *opt2, *opt3, *opt4, *opt5, *opt6, *opt7;

// initialize options
opt1 = "OPEN accountname\n"; // opens new account unless MAX_ACCOUNTS/_NAME is exceeded or accountName already exists
opt2 = "START accountname\n"; // starts customer session
opt3 = "CREDIT amount\n"; // adds amount to account balance (only valid in customer session)
opt4 = "DEBIT amount\n"; // subtracts amount from account balance (only valid in customer session)
opt5 = "BALANCE\n"; // returns current account balance (only valid in customer session)
opt6 = "FINISH\n"; // ends customer session (only valid in customer session)
opt7 = "EXIT\n"; // disconnets client from server
message = "Here are your options:\n\n";

// display options
write(sock, message, strlen(message));
write(sock, opt1, strlen(opt1));
write(sock, opt2, strlen(opt2));
write(sock, opt3, strlen(opt3));
write(sock, opt4, strlen(opt4));
write(sock, opt5, strlen(opt5));
write(sock, opt6, strlen(opt6));
write(sock, opt7, strlen(opt7));

return;
}

/*
* printThread is a function that displays all bank information roughly every PRINT_RATE seconds
*
* printThread takes no arguements because the bank is a global variable
*
* there is no return value
*/
void *printThread(void* theGoods)
{
Bank *bank = (Bank*)theGoods;
int i;

while(1)
{
// try locking bank if succesfull print all account information and then unlock
if (pthread_mutex_trylock(&bank->bank_lock) == 0)
{
i = 0;

// print all account information
for(i; i < MAX_ACCOUNTS; i++)
{
printf("Account ID: %s\n", bank->accounts[i].accountName);
printf("Current Balance: %f\n", bank->accounts[i].balance);
if(bank->accounts[i].session_flag == 1)
printf("Status: In Session\n\n");
else
printf("Status: Not In Session\n\n");
}

// unlock bank_lock and wait untill it is time to print again
pthread_mutex_unlock(&bank->bank_lock);
sleep(PRINT_RATE);
}
// if bank_lock is locked wait 2 seconds and then try again
else
sleep(2);
}
}

/*
* clientServerThread interacts with each client creating a bank client interface
*
* requires a socket descriptor as an arg to interact with client
*
* thread does not return exits when client decides
*/
void *clientServerThread(void *socket_desc)
{
int sock = *(int*)socket_desc;
int bytesRead;
int exitFlag = 0;
char *message;
char *accountInSession;
int accountInSessionNum = MAX_ACCOUNTS + 5;
char acName[MAX_ACCOUNT_NAME];
char buffer[MAX_ACCOUNT_NAME + 6];
char optionBuffer[MAX_ACCOUNT_NAME + 6];
bzero(buffer, MAX_ACCOUNT_NAME + 6);
bzero(optionBuffer, MAX_ACCOUNT_NAME + 6);

// great the new client and prompt them with the options
message = "Greetings! Welcome to Riordan&Hess bank how may we help you?\n";
write(sock, message, strlen(message));
prompt(sock);

sleep(3);
while(exitFlag == 0)
{
// read client choice from socket
bytesRead = read(sock, buffer, MAX_ACCOUNT_NAME + 5);
if (bytesRead <= 0)
error("ERROR read failed");

// convert user input to all lower case for comparison
int i = 0;
while (buffer[i])
{
buffer[i] = tolower(buffer[i]);
i++;
}

// check if client chose opt1 OPEN
strcpy(optionBuffer, "open");
if ((strncmp(buffer, optionBuffer, 4)) == 0)
{
// check if MAX_ACCOUNTS is exceeded
if (bank.total_accounts = MAX_ACCOUNTS)
{
i = 0;
strncpy(acName, buffer+5, MAX_ACCOUNT_NAME);

// check if matching account name already exists
for(i; i <= MAX_ACCOUNTS; i++)
{
int accountLen;
accountLen = sizeof(bank.accounts[i].accountName) - 5;

// if matching account name already exists ask client for new name
if (strncmp(bank.accounts[i].accountName, acName, MAX_ACCOUNT_NAME) == 0)
{
message = "This account name is taken please try again\n\n";
write(sock, message, strlen(message));
prompt(sock);
}

// if there are no previous matches and an empty spot is found create account
else if (bank.accounts[i].exists == 0)
{
// set bank & account mutex
pthread_mutex_lock (&bank.bank_lock);
pthread_mutex_lock (&bank.accounts[i].account_lock);

// initialize account
bank.total_accounts++;
bank.accounts[i].exists = 1;
bank.accounts[i].balance = 0;
bank.accounts[i].session_flag = 1;

// create session
accountInSession = acName;
accountInSessionNum = i;
message = "Account created and session started\n\n";
write(sock, message, strlen(message));

// unlock bank mutex
pthread_mutex_unlock (&bank.bank_lock);

prompt(sock);
}
}
}
// inform client that MAX_ACCOUNTS was exceeded
else
{
message = "We are sorry to inform you that all of our accounts are in use. Please come back and try later";
write(sock, message, strlen(message));
}
}

// check if client chose Start
strcpy(optionBuffer, "start");
if ((strncmp(buffer, optionBuffer, 5)) == 0)
{
// check if client is already in session
if(accountInSessionNum <= MAX_ACCOUNTS)
{
message = "You are already in an account session please exit and then try again";
write(sock, message, strlen(message));
prompt(sock);
}
if (accountInSessionNum > MAX_ACCOUNTS)
{
// check if matching account name exists
for(i; i <= MAX_ACCOUNTS; i++)
{
int accountLen;

strncpy(acName, buffer+6, MAX_ACCOUNT_NAME); // store account name on stack

// if matching account exists try and begin a session
if (strncmp(bank.accounts[i].accountName, acName, MAX_ACCOUNT_NAME) == 0)
{
message = "Account found ";
write(sock, message, strlen(message));

// if the account is not in session begin session
if(bank.accounts[i].session_flag == 0)
{
// lock account mutex and start session
pthread_mutex_lock (&bank.accounts[i].account_lock);
accountInSessionNum = i;
accountInSession = acName;
bank.accounts[i].session_flag = 1;

message = "Session started\n\n";
write(sock, message, strlen(message));
}
// if the account is in session infrom client and tell them to try again
else
{
message = "Account requested is already in session please try again later\n\n";
write(sock, message, strlen(message));
}
}
}
}
else
{
// tell client no matching account exists
message = "No matching account exists";
write(sock, message, strlen(message));
prompt(sock);
}
}

// client has chosen exit disconnect
strcpy(optionBuffer, "exit");
if ((strncmp(buffer, optionBuffer, 4)) == 0)
{
exitFlag = 1;

// check if client is in session->disconnect
if(accountInSessionNum <= MAX_ACCOUNTS)
{
bank.accounts[accountInSessionNum].session_flag = 0;
pthread_mutex_unlock(&bank.accounts[accountInSessionNum].account_lock);
accountInSession = NULL;
accountInSessionNum = MAX_ACCOUNTS + 5;
}
//diconnect
}

// client has chosen credit add to balance
strcpy(optionBuffer, "credit");
if ((strncmp(buffer, optionBuffer, 6)) == 0)
{
char *amount;
float creditAmount;

if (accountInSessionNum <= MAX_ACCOUNTS)
{
// copy amount to new variab;e
strncpy(amount, buffer+6, 20);
creditAmount = (float) atof(amount);

// add amount to balance and inform client
bank.accounts[accountInSessionNum].balance += creditAmount;
message = "Credit succesful";
write(sock, message, strlen(message));

prompt(sock);
}
else
{
// tell client that they are not in a session
message = "You are not currently in an account session please START";
write(sock, message, strlen(message));
prompt(sock);
}
}

// client has chosen debit subtract from balance
strcpy(optionBuffer, "debit");
if ((strncmp(buffer, optionBuffer, 5)) == 0)
{
char *amount;
float debitAmount;

// check if client is in session
if (accountInSessionNum <= MAX_ACCOUNTS)
{
strncpy(amount, buffer+6, 20);
debitAmount = (float) atof(amount);

// check if client's balance is greater than the sum requested
if (bank.accounts[accountInSessionNum].balance > debitAmount)
{
bank.accounts[accountInSessionNum].balance -= debitAmount;
message = "Debit succesful\n\n";
write(sock, message, strlen(message));
}
else
{
message = "You do not have enough funds at this time\n\n";
write(sock, message, strlen(message));
}
prompt(sock);
}
else
{
// tell client that they are not in a session
message = "You are not currently in an account session please START";
write(sock, message, strlen(message));
prompt(sock);
}
}

// client has requested balance
strcpy(optionBuffer, "balance");
if ((strncmp(buffer, optionBuffer, 7)) == 0)
{
if((accountInSessionNum <= MAX_ACCOUNTS))
{
// tell client the balance of accountInSession
sprintf(message, "Current Balance: %f", bank.accounts[accountInSessionNum].balance);
write(sock, message, strlen(message));
prompt(sock);
}
else
{
// tell client the must be in session
message = "You are not currently in an account session please START";
write(sock, message, strlen(message));
prompt(sock);
}
}

strcpy(optionBuffer, "finish");
if ((strncmp(buffer, optionBuffer, 6)) == 0)
{
// if account in session end session
if(accountInSessionNum <= MAX_ACCOUNTS)
{
// end session and inform user
accountInSession = NULL;
accountInSessionNum = MAX_ACCOUNTS + 5;
message = "Session closed\n\n";
write(sock, message, strlen(message));

// Release mutex
pthread_mutex_unlock (&bank.accounts[i].account_lock);
}
else
{
// tell client no matching account exists
message = "You are not currently in an account session\n\n";
write(sock, message, strlen(message));
prompt(sock);
}
}
}
// exit thread
}

/*
* sessionAcceptorThread creates and listens to a socket spawing clientServerThead each time a client connects
*
* recieves bank pointer NOT USED
*
* does not return
*/
void *sessionAcceptorThread(void* bankList)
{
//Bank bank = *(Bank*)bankList;
int socket;
int connection;
struct sockaddr_in peer_Addr;
int addrLen;

// create and bind socket and wait for incoming connections
socket = makeSocket((void *)PORT_NUM);
if(listen(socket, LISTEN_BACKLOG) < 0)
error("ERROR on listening");
addrLen = sizeof(struct sockaddr_in);
pthread_t client_server_thread;

// for each connection spawn clientServerThread
while(connection = accept(socket, (struct sockaddr *) &peer_Addr,(socklen_t*) &addrLen))
{
int TID;
TID = pthread_create(&client_server_thread, NULL, clientServerThread, (void *) &connection);
if (TID < 0)
error("ERROR could not create serv/client thread");
else
printf(" WE GOT A CUSTOMER ");
}
if (connection < 0)
error("ERROR accept failed");


//pthread_exit(NULL);
}

int main()
{
int SA_threadID;
int print_threadID;
uint16_t portNum = PORT_NUM;

//initialize Bank struct with default values
//createBank(&bank);
Bank *bank = (Bank*) malloc(sizeof(struct _Bank));

// build thread status variables for pthread_exit to use later
void* threadStatus0;
void* threadStatus1;

// build thread handles for pthread_create
pthread_t SAthread;
pthread_t POthread;
pthread_t* SAthreadHandle = &SAthread;
pthread_t* POthreadHandle = &POthread;

// build blank pthread attribute structs and initialize them
pthread_attr_t SAthreadAttr;
pthread_attr_t POthreadAttr;
pthread_attr_init(&SAthreadAttr);
pthread_attr_init(&POthreadAttr);

// set the initialized attribute struct so that the pthreads created will be joinable
pthread_attr_setdetachstate(&SAthreadAttr, PTHREAD_CREATE_JOINABLE);
pthread_attr_setdetachstate(&POthreadAttr, PTHREAD_CREATE_JOINABLE);

// set the initialized attribute struct so that the pthreads created will be joinable
pthread_attr_setscope(&SAthreadAttr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setscope(&POthreadAttr, PTHREAD_SCOPE_SYSTEM);

// build the pthreads
SA_threadID = pthread_create(&SAthread, &SAthreadAttr, sessionAcceptorThread, (void *)bank);
if (SA_threadID < 0)
{
printf("errer");
error("ERROR could not create session_acceptor thread");
}
print_threadID = pthread_create(&POthread, &POthreadAttr, printThread, (void *)bank);
if (print_threadID < 0)
error("ERROR could not create print thread");

printf("end of main");
pthread_join(SAthread, &threadStatus0);

//sleep(10);


}

和客户

    */
/*
*serverOut gets server output and prints to client.
*/
void* serverOut(void* serverName)
{
char* server = (char*) serverName;
char bufferS[256];
printf("Getting server output.\n");
while(read(sock, bufferS, sizeof(bufferS)) > 0)
{
printf("%s\n", bufferS);
sleep(2);
}
sleep(2);
pthread_exit(NULL);
}

/*
*userOut gets user input and writes to server.
*If user types 'exit', then they are disconnected.
*/
void* userOut(void* ignore)
{
printf("Sending user input.\n");
char bufferU[256];
while(1)
{
scanf(" %[^\n]}", bufferU);

int i;
while(bufferU[i])
{
bufferU[i] = tolower(bufferU[i]);
i++;
}

write(sock, bufferU, strlen(bufferU) + 1);
/* if(streq(bufferU, "quit")) //scrap
{
pthread_kill(thread, SIGINT);
printf("Disconnected from server.\n");
exit(0);
}*/

if(strcmp(bufferU, "exit") == 0)
{
pthread_kill(thread, SIGINT);
printf("Client disconnected from the server.\n");
exit(0);
}
sleep(2);
}
sleep(2);
pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
int sock = -1;
int portno = -1; //server port to connect to
int n = -1; //utility variable for monitoring reading/writing from/to the socket
char buffer[256]; //char array to store data going to and coming from server
struct sockaddr_in dest; //struct that holds address info for building socket
struct hostent *host; //struct that holds infor about a machine's address

if(argc < 3) //if the user didn't enter enough arguments, complain and exit
{
fprintf(stderr, "usage %s hostname port. Specify server host.\n", argv[0]);
exit(0);
}

portno = atoi(argv[2]); //parse text as an int
host = gethostbyname(argv[1]); //look up IP address that matches
if(host == NULL)
{
fprintf(stderr,"ERROR finding host.\n");
exit(0);
}

char* serverName = argv[1];

// Create the socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0) //if it doesn't work, complain and exit
{
error("ERROR opening socket.\n");
}
printf("Sock created.\n");

printf("Please wait while we connect you to the server.\n\n");
memset(&dest, 0, sizeof(struct sockaddr_in));
//bzero((char *)&dest, sizeof(dest));
//bzero line above may also work

//Prepare the sockaddr_in struct
dest.sin_family = AF_INET; //set a flag to indicate the type of network address
dest.sin_port = htons(5625); //htons change the bit format of a number to network type
//dest.sin_addr.s_addr = 128.6.13.230;

if((host = gethostbyname(serverName)) == NULL)
{
printf("ERROR getting address information.\n");
}
else
{
// do a raw copy of the bytes that represent the server's IP address in
// the 'serverIPAddress' struct into our serverIPAddressInfo struct
bcopy((char *)host->h_addr, (char *)&dest.sin_addr.s_addr, host->h_length);
}

int connectionStatus;
connectionStatus = connect(sock, (const struct sockaddr*) &dest, sizeof(dest));

/* int x = 0; //scrap
while( (x = connect(sock, (const struct sockaddr*) &dest, sizeof(dest)) ) ) //scrap
{
printf("Attempting to connect to %s...\n", serverName);
perror("");
sleep(3);
}*/

while(connectionStatus != 0)
{
printf("Establishing connection to %s.\n", serverName);
connectionStatus = connect(sock, (const struct sockaddr*) &dest, sizeof(dest));
perror("");
sleep(2);
}

if (connect(sock, (struct sockaddr *)&dest, sizeof(dest)) != 0 )
{
error("ERROR connecting.\n");
}

//We are now connected to the server.
printf("You have connected to the server.\n");

pthread_create(&thread, NULL, serverOut, serverName);
pthread_detach(thread);

pthread_create(&handler, NULL, &userOut, NULL);
pthread_detach(thread);

while(write(sock, "0", 2) == 2)
{
sleep(1);
}

pthread_kill(thread, SIGINT);
pthread_kill(handler, SIGINT);

close(sock);

最佳答案

该错误是由于调用 connect() 两次而导致的。

关于c - 错误读取失败: Success (simple multi-threaded server) c programming,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34145160/

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