我目前正在C中构建一个服务器/客户端应用程序。我正在完成任务,因此我无法共享任何代码,但我希望你能帮我解决一些问题。无论如何,关于我的问题。
假设服务器正在运行并接受来自多个客户端的连接。一旦客户端成功建立连接,它就会询问用户要执行的操作 - 让他们调用ACTION 1
和ACTION 2
并假设用户选择第一个并点击 Enter - 所以客户端在套接字上写了代表用户选择的代码,服务器从套接字中读取它并发回代码让客户知道它没问题。
下一步是从用户收集数据并将其发送到服务器。理想情况下,这将按此顺序发生:
当(1)仍在进行时,服务器从(我认为是)空套接字读取并且不等待客户端写入和发送数据。所以(3)发生,服务器明显崩溃。在执行任何需要的操作之前,如何使服务器等待数据?
void *deal_with_user(void *arg)
{
int action = 0;
int status = 0;
ConnectingUser* user = (ConnectingUser *) arg;
action = request_action(user);
if (action == ACTION_1)
{
if ((status = perform_action(user)) != ACTION_GRANTED)
{
pthread_exit((void *) 0);
}
}
else if (action == ACTION_2)
{
// do nothing yet
}
else
{
pthread_exit((void *) 0);
}
/*
*
* More code...
*
*/
pthread_exit((void *) 0);
}
int request_action(ConnectingUser *user)
{
int status = 0;
while (!status)
{
status = read_user_action(user);
/*
*
* Error Handling code
*
*/
return status;
}
int read_user_action(ConnectingUser *user)
{
int read_bytes;
int status;
char *action_code;
read_bytes = 0;
action_code = (char *) calloc (4, sizeof(char));
if ((read_bytes = read(user->user_socket_descriptor, action_code, 4)) <= 0)
{
if (read_bytes < 0)
{
fprintf(stderr, "Error read_user_action()\n");
status = READ_ACTION_ERR;
}
else if (read_bytes == 0)
{
status = BROKEN_PIPE;
}
}
else
{
if (write(user->user_socket_descriptor, "OKCODE", 6) < 0)
{
fprintf(stderr, "Error read_user_action()\n");
free(action_code);
return WRITE_ACTION_ERR;
}
// get_action() returns either ACTION_1 or ACTION_2
status = get_action(action_code);
}
free(action_code);
return status;
}
int perform_action(ConnectingUser *user)
{
int status = 0;
while (!status)
{
status = authorize_action(user);
/*
*
* Error Handling code
*
*/
return status;
}
int authorize_action(ConnectingUser *user)
{
int read_bytes;
int status;
char *action_data;
NeededData *client_data = NULL;
read_bytes = 0;
action_data = (char *) malloc (MAX_LENGTH*sizeof(char));
if ((read_bytes = read(user->user_socket_descriptor, action_data, MAX_LENGTH)) <= 0)
{
if (read_bytes < 0)
{
fprintf(stderr, "Error authorize_action()\n");
free(action_data);
return READ_DATA_ERR;
}
else if (read_bytes == 0)
{
free(action_data);
return BROKEN_PIPE;
}
}
else
{
printf("I have read something: %s\n", action_data);
}
if (checks_out(user, user_list, client_data))
{
if (write(user->user_socket_descriptor, "OK-ACT", 6) < 0)
{
fprintf(stderr, "Errore authorize_login(): impossibile inviare auth\n");
free(action_data);
free(client_data);
return WRITE_INFO_ERR;
}
status = ACTION_GRANTED;
}
else
{
if (write(user->user_socket_descriptor, "NO-ACT", 6) < 0)
{
fprintf(stderr, "Errore authorize_login(): impossibile inviare auth\n");
free(action_data);
free(client_data);
return WRITE_INFO_ERR;
}
status = INCORRECT_ACTION;
}
free(action_data);
free(client_data);
return status;
}
int ask_for_action()
{
int action = 0;
int status = 0;
char *input;
input = (char *) calloc(2, sizeof(char));
while (!status)
{
fprintf(stdout, "Pick action\n");
fprintf(stdout, "[1] Action One\n[2] Action Two\n\nInput: ");
fgets(input, 2, stdin);
getchar();
/*
*
* Error Handling code
*
*/
action = write_action(action);
status = action_one();
/*
*
* Error Handling code
*
*/
}
}
free(input);
return action;
}
int write_action(const int action)
{
int read_chars;
char *action_code;
char *server_ans;
/*
*
* More code
*
*/
// Stores the action code
action_code = (char *) calloc (4, sizeof(char));
// Stores server response
server_ans = (char *) calloc (6, sizeof(char));
if (write(socket_descriptor, action_code, sizeof(action_code)) < 0)
{
fprintf(stderr, "Errore write_action()\n");
free(action_code);
return WRITE_ACTION_ERR;
}
free(action_code);
if ((read_chars = read(socket_descriptor, server_ans, 6)) <= 0)
{
/*
*
* Error Handling
*
*/
}
if (strncmp(server_ans, "OK-ACT", 6) == 0)
{
if (cc.debug)
{
fprintf(stdout, "Action sent correctly.\n");
}
free(server_ans);
return action;
}
// Code...
}
int action_one()
{
// Server should wait for this function to gather input from user, but by
// the time this is called, the server has moved on and crashed.
}
我发现在客户端发送动作代码之后,服务器读取3个字节---未在屏幕上打印出来,它们是\0
或\n
,我猜---在崩溃之前。我试过刷新输入,但它没有摆脱这些字节并继续读取它们。