gpt4 book ai didi

c - 不采用else分支的多线程代码

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:17:23 25 4
gpt4 key购买 nike

我目前正在用 C 语言为 Linux 编写一个原始的客户端-服务器程序。服务器是多线程的。我分别为客户端和服务器编写了以下代码:

服务器(使用gcc -o -lpthreads server server.c 编译):

#include <stdio.h>                      
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>


void lsfunc(char *path, char *buffer) {
int pointer = sprintf(buffer, "User ID\tGroup ID\tFilename\n");
int cx = 0;
DIR *mydir;
struct dirent *myfile;
struct stat mystat;
mydir = opendir(path);
myfile = readdir(mydir);
while ((myfile = readdir(mydir)) != NULL) {
stat(myfile->d_name, &mystat);
cx = sprintf(buffer+pointer, "%lu\t%lu\t%s\n", (unsigned long int) mystat.st_uid, (unsigned long int) mystat.st_gid, myfile->d_name);
pointer += cx;
}
closedir(mydir);
}

void makedir(char *path, char *prompt) {
struct stat st = {0};
if (stat(path, &st) == -1) {
mkdir(path, 0700);
sprintf(prompt, "Directory successfully created");
}
else {
sprintf(prompt, "A folder with the same name already exists");
}
}

void fgetsfunc(char *path, char *buffer) {
FILE *fp = fopen(path, "r");
char ch;
int pointer = 0;
while ((ch = getc(fp)) != EOF) {
sprintf(buffer+pointer, "%c", ch);
pointer += 1;
}
fclose(fp);
}

void fputsfunc(char *path, char *buffer) {
int resultCode = 0;
FILE *fp = fopen(path, "w");
resultCode = fputs(buffer, fp);
if (resultCode == EOF) {
fprintf(stderr, "Failed to write.\n");
}
fclose(fp);
}

int authenticate(char *username) {
int error = 0;
if (*username != 'u') {
error = -1;
}
*username++;
while (*username != '\0') {
if (!isdigit(*username)) {
error = -1;
}
*username++;
}
return error;
}


void *connectionHandler(void *socket_descriptor) {
int rcv_retcode, wrt_retcode, error_code;
int sock = *(int*)socket_descriptor;
char message_received[100], message_sent[10000];
char user[5];
char *greetings;
char *FAIL = "FAIL";

greetings = "Welcome user. Enter your username: ";
write(sock, greetings, strlen(greetings));

if((rcv_retcode = recv(sock, user, 5, 0)) == -1) {
perror("Receive failed");
}

error_code = authenticate(user);

if (error_code < 0) {
fprintf(stderr, "Failed to authenticate user.\n");
write(sock, FAIL, 5);
}

while(1) {
if((rcv_retcode = recv(sock, message_received, 100, 0)) == -1) {
perror("Receive failed");
}

fprintf(stdout, "Client says: %s\n",message_received);
const char s[2] = " ";
const char n[2] = "\n";
char *token, *command, *path, *input;
//char writeBuff[1000];
token = strtok(message_received, s);
command = token;

if (strcmp(command, "exit") == 0) {
close(sock);
strncpy(message_sent, "Client logged out.", 10000);
}

else if (strcmp(command,"ls") == 0) {
token = strtok(NULL, s);
path = token;
lsfunc(path, message_sent);
}

else if(strcmp(command,"mkdir") == 0) {
token = strtok(NULL, s);
path = token;
makedir(path, message_sent);
}

else if(strcmp(command,"fgets") == 0) {
token = strtok(NULL, s);
path = token;
fgetsfunc(path, message_sent);
}

else if(strcmp(command, "fputs") == 0) {
token = strtok(NULL, s);
path = token;
token = strtok(NULL, n);
input = token;
printf("%s\n", input);
fputsfunc(path, input);
strncpy(message_sent, "Written to file", 10000);
}
if ((wrt_retcode = write(sock, message_sent, 10000)) == -1) {
perror("Write failed");
}
message_received[0] = '\0';
message_sent[0] = '\0';
//sleep(1);
}
close(sock);
}


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

int socket_retcode, bind_retcode, listen_retcode, acc_retcode, rcv_retcode, wrt_retcode;
char message_received[100], message_sent[10000];
struct sockaddr_in server, client;

if ((socket_retcode = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Failed to create socket");
return -1;
}

fprintf(stdout, "Socket created successfully\n");

server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(4000);
char *server_add = inet_ntoa(server.sin_addr);
uint16_t port_num = ntohs(server.sin_port);
printf("The address of the server is: %s\nThe port number is: %d\n", server_add,port_num);

if ((bind_retcode = bind(socket_retcode, (struct sockaddr*)&server, sizeof(server))) == -1) {
perror("Bind failed");
return -1;
}

if((listen_retcode = listen(socket_retcode, 20)) == -1) {
perror("Listen failed");
return -1;
}
int c = sizeof(struct sockaddr_in);
pthread_t thread_id;

while ((acc_retcode = accept(socket_retcode, (struct sockaddr*)&client, (socklen_t*)&c))) {
printf("Connection accepted\n");

if (pthread_create (&thread_id, NULL, connectionHandler, (void*)&acc_retcode) < 0) {
perror("Thread creation failed");
}

printf("Handler assigned\n");
}
if (acc_retcode < 0) {
perror("Accept failed");
return -1;
}
return 0;
}

客户:

#include <stdio.h>              
#include <string.h>
#include <arpa/inet.h>

#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2

static int getLine(char *prompt, char *buff, size_t sz) {
int ch, extra;

if (prompt != NULL) {
printf ("%s", prompt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL) {
return NO_INPUT;
}

if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}

buff[strlen(buff)-1] = '\0';
return OK;
}

int main(int argc, char *argv[]) {
char IP[20], message[100], rcv_message[10000], filewriter_buffer[10000], check;
char greeting[100], username[5], user_auth[5];

int port_num, flag = 1;
int client_retcode, IP_retcode, message_retcode, cnct_retcode, send_retcode, rcv_retcode;
int logon_rcv, send_usr, user_rcv;

struct sockaddr_in r_server;
client_retcode = socket(AF_INET,SOCK_STREAM,0);

if (client_retcode == -1) {
perror("Failed to create socket.");
return -1;
}

if (getLine("Enter IP: ", IP, sizeof(IP)) != OK) {
fprintf(stderr, "No/Invalid IP provided.\n");
return -1;
}

fprintf(stdout, "Enter Port Number: ");

if (scanf("%d%c", &port_num, &check) != 2 || check != '\n') {
printf("Non-integer port provided.\n");
return -1;
}

r_server.sin_family = AF_INET;
r_server.sin_port = htons(port_num);
r_server.sin_addr.s_addr = inet_addr(IP);
cnct_retcode = connect(client_retcode, (struct sockaddr *)&r_server, sizeof(r_server));

if (cnct_retcode == -1) {
perror("Connect failed");
return -1;
}

fprintf(stdout, "Connection to server on %s:%d successful\n", IP, port_num);

while(1) {
logon_rcv = recv(client_retcode, greeting, 100, 0);
if (logon_rcv == -1) {
perror("Receive failed");
}
if (getLine(greeting, username, sizeof(username)) != OK) {
printf("No/Invalid input\n");
return -1;
}

send_usr = send(client_retcode, username, 5, 0);
if (send_usr == -1) {
perror("Send failed");
return -1;
}

user_rcv = recv(client_retcode, user_auth, 5, 0);

if (user_rcv == -1) {
perror("Receive failed");
return -1;
}


if (strcmp(user_auth, "FAIL") == 0) {
fprintf(stderr, "Wrong username. Exiting...\n");
break;
}

else {

if (getLine("Enter command: ", message, sizeof(message)) != OK) {
printf("No/Invalid command provided\n");
return -1;
}

if(strcmp(message, "exit") == 0) {
send_retcode = send(client_retcode, message, 100, 0);
if(send_retcode == -1) {
perror("Send failed");
return -1;
}
break;
}

send_retcode = send(client_retcode, message, 100, 0);
if(send_retcode == -1) {
perror("Send failed");
return -1;
}

rcv_retcode = recv(client_retcode, rcv_message, 10000, 0);

if (rcv_retcode == -1) {
perror("Receive failed");
return -1;
}
printf("Server says: %s\n", rcv_message);
message[0] = '\0';
rcv_message[0] = '\0';
}
close(client_retcode);
}
return 0;
}

从代码中可以清楚地看出,我不是一个非常优秀的 C 程序员。执行程序时,我到了客户端提供用户名和服务器检查其有效性的地步。问题是:在那之后它停止了。如果用户名有效,则客户端的 else 分支将永远不会被采用,之后在相应的 shell 上也不会发生任何事情。如果我取出整个 if-else 并且不检查有效的用户名,它会工作得很好,但这是我实现的一个重要部分,我不能没有它。我做错了什么?

最佳答案

存在许多严重错误,但我认为您看到所描述行为的原因是:

server.c中:

if((rcv_retcode = recv(sock, user, 5, 0)) == -1) {
perror("Receive failed");
}

error_code = authenticate(user);

if (error_code < 0) {
fprintf(stderr, "Failed to authenticate user.\n");
write(sock, FAIL, 5);
}

while(1) {
if((rcv_retcode = recv(sock, message_received, 100, 0)) == -1) {
perror("Receive failed");
}
...
}

如果用户名有效,您的服务器不会返回任何响应,只是等待。如果用户名有效,您的服务器需要响应,否则您的客户端将永远等待在 client.c 中:

    /* Ends up waiting here forever */
user_rcv = recv(client_retcode, user_auth, 5, 0);

if (user_rcv == -1) {
perror("Receive failed");
return -1;
}


if (strcmp(user_auth, "FAIL") == 0) {
fprintf(stderr, "Wrong username. Exiting...\n");
break;
}

要解决此问题,请更改 server.c(由注释指示):

if((rcv_retcode = recv(sock, user, 5, 0)) == -1) {
perror("Receive failed");
}

error_code = authenticate(user);

if (error_code < 0) {
fprintf(stderr, "Failed to authenticate user.\n");
write(sock, FAIL, 5);
}

write(sock, "butt", 5); /* Send something that isn't FAIL */

while(1) {
if((rcv_retcode = recv(sock, message_received, 100, 0)) == -1) {
perror("Receive failed");
}
...
}

关于c - 不采用else分支的多线程代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28129725/

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