以下代碼(最后)表示執行緒函式,它從遠程客戶端接收 ls 命令并將當前作業目錄發送到該客戶端。
它成功發送但有一個問題:當它完全停止發送時,我希望它再次開始收聽。在線:
printf("Enter 1 if you want to exit or 0 if you don't: ");
fgets(exit_status,MAX_SIZE,stdin);
當我按 Enter 時,它卡住并終止(并啟動另一個執行緒)
我不明白為什么?當我除錯時,我看到上面的列印陳述句在按 Enter 后執行,盡管除錯器位于函式的末尾(意味著它通過了這個列印陳述句)。
我希望它在完成發送資料后自動重新開始收聽。
如果有人想查看我的完整代碼,請點擊以下鏈接:https ://pastebin.com/9UmTkPge
void *server_socket_ls(void *arg) {
int* exit_status = (int*)malloc(sizeof(int));
*exit_status = 0;
while (*exit_status == 0) {
//socket code is here
//code for ls
char buffer[BUFFSIZE];
int received = -1;
char data[MAX];
memset(data,0,MAX);
// this will make server wait for another command to run until it receives exit
data[0] = '\0';
if((received = recv(new_socket, buffer,BUFFSIZE,0))<0){
perror("Failed");
}
buffer[received] = '\0';
strcat (data, buffer);
if (strcmp(data, "exit")==0) // this will force the code to exit
exit(0);
puts (data);
char *args[100];
setup(data,args,0);
int pipefd[2],lenght;
if(pipe(pipefd))
perror("Failed to create pipe");
pid_t pid = fork();
char path[MAX];
if(pid==0)
{
close(1); // close the original stdout
dup2(pipefd[1],1); // duplicate pipfd[1] to stdout
close(pipefd[0]); // close the readonly side of the pipe
close(pipefd[1]); // close the original write side of the pipe
execvp(args[0],args); // finally execute the command
}
else
if(pid>0)
{
close(pipefd[1]);
memset(path,0,MAX);
while(lenght=read(pipefd[0],path,MAX-1)){
printf("Data read so far %s\n", path);
if(send(new_socket,path,strlen(path),0) != strlen(path) ){
perror("Failed");
}
//fflush(NULL);
printf("Data sent so far %s\n", path);
memset(path,0,MAX);
}
close(pipefd[0]);
//removed so server will not terminate
}
else
{
printf("Error !\n");
exit(0);
}
printf("Enter 1 if you want to exit or 0 if you don't: ");
fgets(exit_status,MAX_SIZE,stdin);
}
}
uj5u.com熱心網友回復:
有很多錯誤:
- In
terminal_thread,input_command是在每次回圈迭代時分配的——記憶體泄漏 - 去除換行符的代碼被破壞
- 使用
.l,不指定 IP 地址會導致段錯誤,token因為NULL terminal_threadfor中的埠號.l是 5126與對應服務器代碼中的 9191不匹配- 連接后,
server_socket_file什么都不做。 - 在
server_socket_ls中,它在、、和上回圈。回圈應該在之后開始(即只在回圈中執行并重用監聽套接字)。socketbindlistenacceptlistenaccept - 代碼中標記的其他錯誤
我不得不重構代碼并添加一些除錯。它帶有錯誤注釋。我使用cpp條件來表示舊代碼與新代碼:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
這是代碼。我得到了最小的 .l(遠程ls)作業:
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <stdarg.h>
#define BACKLOG 10
#define MAX_SIZE 200
#define BACKLOG 10
#define BUFFSIZE 2048
#define MAXPENDING 5
#define MAX 2048
__thread char *tid;
__thread char dbgstrbuf[1000];
FILE *xfdbg;
typedef struct server_arg {
int portNum;
} server_arg;
typedef struct server_arg1 {
int portNum;
} server_arg1;
void
dbgprt(const char *fmt,...)
{
va_list ap;
char msg[1000];
char *bp = msg;
bp = sprintf(bp,"%4s ",tid);
va_start(ap,fmt);
bp = vsprintf(bp,fmt,ap);
va_end(ap);
fputs(msg,xfdbg);
}
const char *
dbgstr(const char *str)
{
char *bp = dbgstrbuf;
bp = sprintf(bp,"'");
for (int chr = *str ; chr != 0; chr = *str ) {
if ((chr > 0x20) && (chr <= 0x7E))
bp = sprintf(bp,"%c",chr);
else
bp = sprintf(bp,"{%2.2X}",chr);
}
bp = sprintf(bp,"'");
return dbgstrbuf;
}
void
setup(char inputBuffer[], char *args[], int *background)
{
const char s[4] = " \t\n";
char *token;
token = strtok(inputBuffer, s);
int i = 0;
while (token != NULL) {
args[i] = token;
i ;
// printf("%s\n", token);
token = strtok(NULL, s);
}
args[i] = NULL;
}
void *
terminal_thread(void *arg)
{
// NOTE/FIX: do this _once_
#if 1
char *input_command = malloc(MAX_SIZE);
#endif
tid = "term";
while (1) {
dbgprt("term: PROMPT\n");
printf(">> ");
//memset(input_command,0,strlen(str));
// NOTE/BUG: this is a memory leak
#if 0
char *input_command = malloc(MAX_SIZE);
#endif
dbgprt("term: FGETS\n");
fgets(input_command, MAX_SIZE, stdin);
// NOTE/BUG: code is broken to strip newline
#if 0
if ((strlen(input_command) > 0) &&
(input_command[strlen(input_command) - 1] == '\n'))
input_command[strlen(input_command) - 1] = '\0';
#else
input_command[strcspn(input_command,"\n")] = 0;
#endif
dbgprt("term: COMMAND %s\n",dbgstr(input_command));
char list[] = "ls";
char cp[] = "cp";
#if 0
char s[100];
printf("%s\n", getcwd(s,100));
chdir("Desktop");
printf("%s\n", getcwd(s,100));
#endif
if (strcmp(input_command, list) == 0) {
// ls code will run here
}
if (strchr(input_command, '.') != NULL &&
strchr(input_command, 'l') != NULL) {
printf("remote ls\n");
char ip[20];
const char c[2] = " ";
// strcpy(str,input_command);
char *token;
// get the first token
token = strtok(input_command, c);
// walk through other tokens
int i = 0;
while (token != NULL && i != -1) {
token = strtok(NULL, c);
i--;
}
// NOTE/FIX: after the loop token _must_ be
#if 1
if (token == NULL) {
token = "127.0.0.1";
printf("no IP address found -- using %s\n",token);
}
#endif
strcpy(ip, token);
int sock;
struct sockaddr_in echoserver;
char buffer[BUFFSIZE];
unsigned int echolen;
int received = 0;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("Failed to create socket");
exit(1);
}
int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(int)) < 0) {
perror("error");
}
memset(&echoserver, 0, sizeof(echoserver));
echoserver.sin_family = AF_INET;
echoserver.sin_addr.s_addr = inet_addr(ip);
// NOTE/BUG: this port number does _not_ match any server port
#if 0
echoserver.sin_port = htons(5126);
#else
unsigned short port = 9191;
dbgprt("term: port=%u\n",port);
echoserver.sin_port = htons(port);
#endif
if (connect(sock, (struct sockaddr *) &echoserver,
sizeof(echoserver)) < 0) {
perror("Failed to connect with server");
exit(1);
}
char s[100];
// while(1) { // to repeat the whole process until exit is typed
strcpy(s, "ls");
// NOTE/BUG: this blows away the "s" in "ls" because s is _set_ with strcpy
#if 0
s[strlen(s) - 1] = '\0'; // fgets doesn't automatically discard '\n'
#endif
echolen = strlen(s);
/* send() from client; */
if (send(sock, s, echolen, 0) != echolen) {
perror("Mismatch in number of sent bytes");
}
fprintf(stdout, "Message from server: ");
int bytes = 0;
/* recv() from server; */
if ((bytes = recv(sock, buffer, echolen, 0)) < 1) {
perror("Failed to receive bytes from server");
}
received = bytes;
buffer[bytes] = '\0';
/* Assure null terminated string */
fprintf(stdout, buffer);
bytes = 0;
// this d {...} while block will receive the buffer sent by server
do {
buffer[bytes] = '\0';
printf("%s\n", buffer);
} while ((bytes = recv(sock, buffer, BUFFSIZE - 1, 0)) >= BUFFSIZE - 1);
buffer[bytes] = '\0';
printf("%s\n", buffer);
printf("\n");
continue;
}
}
}
void *
server_socket_ls(void *arg)
{
int *exit_status = (int *) malloc(sizeof(int));
tid = "ls";
dbgprt("ls: ENTER\n");
*exit_status = 0;
while (*exit_status == 0) {
server_arg *s = (server_arg *) arg;
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
dbgprt("ls: SOCKET\n");
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
int enable = 1;
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(int)) < 0) {
perror("error");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(s->portNum);
dbgprt("ls: BIND prtNum=%u\n",s->portNum);
if (bind(server_fd, (struct sockaddr *) &address, sizeof(address))
< 0) {
perror("bind failed");
}
dbgprt("ls: LISTEN\n");
if (listen(server_fd, 3) < 0) {
perror("listen");
}
if ((new_socket = accept(server_fd, (struct sockaddr *) &address,
(socklen_t *) & addrlen)) < 0) {
perror("accept");
}
dbgprt("ls: ACCEPTED\n");
printf("Server Connected\n");
//code for ls
char buffer[BUFFSIZE];
int received = -1;
char data[MAX];
memset(data, 0, MAX);
// this will make server wait for another command to run until it
// receives exit
data[0] = '\0';
if ((received = recv(new_socket, buffer, BUFFSIZE, 0)) < 0) {
perror("Failed");
}
buffer[received] = '\0';
strcat(data, buffer);
dbgstr(data);
if (strcmp(data, "exit") == 0) // this will force the code to exit
exit(0);
puts(data);
char *args[100];
setup(data, args, 0);
int pipefd[2],
lenght;
if (pipe(pipefd))
perror("Failed to create pipe");
pid_t pid = fork();
char path[MAX];
if (pid == 0) {
// NOTE/BUG: no need to close before dup2
#if 0
close(1); // close the original stdout
#endif
dup2(pipefd[1], 1); // duplicate pipfd[1] to stdout
close(pipefd[0]); // close the readonly side of the pipe
close(pipefd[1]); // close the original write side of the pipe
execvp(args[0], args); // finally execute the command
}
else if (pid > 0) {
close(pipefd[1]);
memset(path, 0, MAX);
// NOTE/BUG: read does _not_ terminate buffer with EOS (0x00)
#if 0
while (lenght = read(pipefd[0], path, MAX - 1)) {
printf("Data read so far %s\n", path);
if (send(new_socket, path, strlen(path), 0) != strlen(path)) {
perror("Failed");
}
// fflush(NULL);
printf("Data sent so far %s\n", path);
memset(path, 0, MAX);
}
#else
while (lenght = read(pipefd[0], path, MAX - 1)) {
printf("Data read so far ", path);
fwrite(path,1,lenght,stdout);
printf("\n");
if (send(new_socket, path, lenght, 0) != lenght) {
perror("Failed");
}
// fflush(NULL);
printf("Data send so far ", path);
fwrite(path,1,lenght,stdout);
printf("\n");
memset(path, 0, MAX);
}
#endif
// close(pipefd[0]);
// removed so server will not terminate
// NOTE/BUG: child needs to terminate -- otherwise, _both_ parent and child
// will prompt user below
#if 1
exit(0);
#endif
}
else {
printf("Error !\n");
exit(0);
}
printf("Enter 1 if you want to exit or 0 if you don't: ");
// NOTE/BUG: need to pass buffer
// NOTE/BUG: exit_status is an int pointer
#if 0
fgets(exit_status, MAX_SIZE, stdin);
#else
char exit_buf[100];
fgets(exit_buf,sizeof(exit_buf),stdin);
*exit_status = atoi(exit_buf);
#endif
}
}
void *
server_socket_file(void *arg)
{
tid = "file";
dbgprt("file: ENTER\n");
server_arg1 *s1 = (server_arg1 *) arg;
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
int enable = 1;
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int))
< 0) {
perror("error");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(s1->portNum);
dbgprt("file: BIND portNum=%u\n",s1->portNum);
if (bind(server_fd, (struct sockaddr *) &address, sizeof(address)) < 0) {
perror("bind failed");
}
if (listen(server_fd, 3) < 0) {
perror("listen");
}
if ((new_socket = accept(server_fd, (struct sockaddr *) &address,
(socklen_t *) & addrlen)) < 0) {
perror("accept");
}
printf("Server Connected\n");
}
int
main(int argc, char const *argv[])
{
tid = "main";
server_arg *s = (server_arg *) malloc(sizeof(server_arg));
server_arg1 *s1 = (server_arg1 *) malloc(sizeof(server_arg1));
pthread_t id_1;
pthread_t id_2;
pthread_t id_3;
xfdbg = fopen("debug.txt","w");
setlinebuf(xfdbg);
if (pthread_create(&id_3, NULL, terminal_thread, NULL) != 0) {
perror("pthread_create");
}
// NOTE/BUG: this port (or the one below) doesn't match the client code
// port of 5126
s->portNum = 9191;
pthread_create(&id_1, NULL, server_socket_ls, s);
s1->portNum = 6123;
pthread_create(&id_2, NULL, server_socket_file, s1);
pthread_join(id_1, NULL);
pthread_join(id_2, NULL);
pthread_join(id_3, NULL);
// NOTE/BUG: pthread_exit in main thread is wrong
#if 0
pthread_exit(0);
#else
return 0;
#endif
}
這是程式輸出(對于.l):
>> remote ls
no IP address found -- using 127.0.0.1
Message from server: Server Connected
ls
Data read so far debug.txt
orig
orig.c
orig.txt
out
Data send so far debug.txt
orig
orig.c
orig.txt
out
bug.txt
orig
orig.c
orig.txt
out
這是debug.txt輸出:
term term: PROMPT
term term: FGETS
ls ls: ENTER
ls ls: SOCKET
file file: ENTER
ls ls: BIND prtNum=9191
file file: BIND portNum=6123
ls ls: LISTEN
term term: COMMAND '.l'
term term: port=9191
ls ls: ACCEPTED
term term: PROMPT
該程式在 exit(0) 停止發送資料后立即退出,因此不要求 exit_status。有沒有辦法讓它不停止,而是終端提示與在后面監聽的服務器一起重新出現?– 德拉古特
因為我感覺到了緊迫性,所以我錯誤地認為現在部分解決方案比完美解決方案為時已晚。
exit我可能在 ls 服務器父行程中引入了一個帶有無關呼叫的錯誤(現已修復)。
但是,還有其他問題...
主要問題是服務器(對于 ls )正在提示用戶是否繼續(on stdout/stdin)。這不太好用。
應該提示用戶的是客戶端(即)。terminal_thread或者,正如我所做的那樣,客戶端將exit在命令提示符下看到,然后將包含“exit”的資料包發送到服務器,然后終止。然后,服務器將看到此命令并終止。
我在沒有完全重做所有內容的情況下盡可能多地重構。
我將一些代碼拆分為函式。一些可以/可以重用來實作“檔案”服務器。
但是,我會將這兩個函式都放在一個服務器執行緒中。我會讓服務器查看它獲得的“命令”并根據命令執行任一操作。由于在“檔案”服務器中沒有實際做某事的代碼 [然而] 很難返工。
要解決的一件事[我沒有時間]:
該.l命令的格式為:.l [ip_address]. 的默認ip_address值為127.0.0.1。但是,這應該分為兩個命令(例如):
- 附加 [ip_address]
- ls [ls 引數]
無論如何,這是更新的代碼。我不得不快一點移動,所以它沒有我想要的那么干凈。
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <stdarg.h>
#if 1
#include <time.h>
#endif
#define BACKLOG 10
#define MAX_SIZE 200
#define BACKLOG 10
#define BUFFSIZE 2048
#define MAXPENDING 5
#define MAX 2048
__thread char *tid;
__thread char dbgstrbuf[1000];
FILE *xfdbg;
double tsczero = 0.0;
typedef struct server_arg {
int portNum;
} server_arg;
typedef struct server_arg1 {
int portNum;
} server_arg1;
double
tscgetf(void)
{
struct timespec ts;
double sec;
clock_gettime(CLOCK_MONOTONIC,&ts);
sec = ts.tv_nsec;
sec /= 1e9;
sec = ts.tv_sec;
sec -= tsczero;
return sec;
}
void
dbgprt(const char *fmt,...)
{
va_list ap;
char msg[1000];
char *bp = msg;
bp = sprintf(bp,"[%.9f/%4s] ",tscgetf(),tid);
va_start(ap,fmt);
bp = vsprintf(bp,fmt,ap);
va_end(ap);
fputs(msg,xfdbg);
}
const char *
dbgstr(const char *str,int len)
{
char *bp = dbgstrbuf;
if (len < 0)
len = strlen(str);
bp = sprintf(bp,"'");
for (int i = 0; i < len; i) {
int chr = str[i];
if ((chr > 0x20) && (chr <= 0x7E))
bp = sprintf(bp,"%c",chr);
else
bp = sprintf(bp,"{%2.2X}",chr);
}
bp = sprintf(bp,"'");
return dbgstrbuf;
}
void
setup(char inputBuffer[], char *args[], int *background)
{
const char s[4] = " \t\n";
char *token;
token = strtok(inputBuffer, s);
int i = 0;
while (token != NULL) {
args[i] = token;
i ;
// printf("%s\n", token);
token = strtok(NULL, s);
}
args[i] = NULL;
}
int
open_remote(const char *ip,unsigned short port)
{
int sock;
struct sockaddr_in echoserver;
dbgprt("open_remote: ENTER ip=%s port=%u\n",dbgstr(ip,-1),port);
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("Failed to create socket");
exit(1);
}
int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(int)) < 0) {
perror("error");
}
memset(&echoserver, 0, sizeof(echoserver));
echoserver.sin_family = AF_INET;
echoserver.sin_addr.s_addr = inet_addr(ip);
// NOTE/BUG: this port number does _not_ match any server port
#if 0
echoserver.sin_port = htons(5126);
#else
dbgprt("term: port=%u\n",port);
echoserver.sin_port = htons(port);
#endif
if (connect(sock, (struct sockaddr *) &echoserver,
sizeof(echoserver)) < 0) {
perror("Failed to connect with server");
exit(1);
}
dbgprt("open_remote: EXIT sock=%d\n",sock);
return sock;
}
void *
terminal_thread(void *arg)
{
// NOTE/FIX: do this _once_
#if 1
char *input_command = malloc(MAX_SIZE);
#endif
tid = "term";
char buffer[BUFFSIZE];
int sock_ls = -1;
while (1) {
dbgprt("term: PROMPT\n");
printf(">> ");
//memset(input_command,0,strlen(str));
// NOTE/BUG: this is a memory leak
#if 0
char *input_command = malloc(MAX_SIZE);
#endif
dbgprt("term: FGETS\n");
fgets(input_command, MAX_SIZE, stdin);
// NOTE/BUG: code is broken to strip newline
#if 0
if ((strlen(input_command) > 0) &&
(input_command[strlen(input_command) - 1] == '\n'))
input_command[strlen(input_command) - 1] = '\0';
#else
input_command[strcspn(input_command,"\n")] = 0;
#endif
dbgprt("term: COMMAND %s\n",dbgstr(input_command,-1));
char list[] = "ls";
char cp[] = "cp";
#if 0
char s[100];
printf("%s\n", getcwd(s,100));
chdir("Desktop");
printf("%s\n", getcwd(s,100));
#endif
// exit program (and exit server)
if (strcmp(input_command,"exit") == 0) {
if (sock_ls >= 0) {
dbgprt("term: SENDEXIT\n");
if (send(sock_ls,"exit",4,0) < 0) {
perror("send/exit");
exit(1);
}
break;
}
}
if (strcmp(input_command, list) == 0) {
// ls code will run here
}
if ((input_command[0] == '.') && (input_command[1] == 'l')) {
printf("remote ls\n");
char ip[20];
const char c[2] = " ";
// strcpy(str,input_command);
char *token;
// get the first token
token = strtok(input_command, c);
// walk through other tokens
int i = 0;
while (token != NULL && i != -1) {
token = strtok(NULL, c);
i--;
}
#if 1
if (token == NULL) {
token = "127.0.0.1";
printf("no IP address found -- using %s\n",token);
}
#endif
if (sock_ls < 0)
sock_ls = open_remote(token,9191);
char s[100];
strcpy(s, "ls");
// NOTE/BUG: this blows away the "s" in "ls" because s is _set_ with strcpy
#if 0
s[strlen(s) - 1] = '\0'; // fgets doesn't automatically discard '\n'
#endif
unsigned int echolen;
echolen = strlen(s);
int received = 0;
/* send() from client; */
if (send(sock_ls, s, echolen, 0) != echolen) {
perror("Mismatch in number of sent bytes");
}
fprintf(stdout, "Message from server: ");
int bytes = 0;
/* recv() from server; */
if ((bytes = recv(sock_ls, buffer, echolen, 0)) < 1) {
perror("Failed to receive bytes from server");
}
received = bytes;
buffer[bytes] = '\0';
/* Assure null terminated string */
fprintf(stdout, buffer);
bytes = 0;
// this d {...} while block will receive the buffer sent by server
do {
buffer[bytes] = '\0';
printf("%s\n", buffer);
} while ((bytes = recv(sock_ls, buffer, BUFFSIZE - 1, 0)) >= BUFFSIZE - 1);
buffer[bytes] = '\0';
printf("%s\n", buffer);
printf("\n");
continue;
}
}
dbgprt("term: EXIT\n");
return (void *) 0;
}
int
ls_loop(int new_socket)
{
dbgprt("ls_loop: ENTER new_socket=%d\n",new_socket);
//code for ls
char buffer[BUFFSIZE];
int received = -1;
char data[MAX];
int stop = 0;
while (1) {
memset(data, 0, MAX);
// this will make server wait for another command to run until it
// receives exit
data[0] = '\0';
if ((received = recv(new_socket, buffer, BUFFSIZE, 0)) < 0) {
perror("Failed");
}
buffer[received] = '\0';
strcpy(data, buffer);
dbgprt("ls_loop: COMMAND %s\n",dbgstr(data,-1));
// this will force the code to exit
#if 0
if (strcmp(data, "exit") == 0)
exit(0);
puts(data);
#else
if (strncmp(data, "exit", 4) == 0) {
dbgprt("ls_loop: EXIT/COMMAND\n");
stop = 1;
break;
}
#endif
char *args[100];
setup(data, args, 0);
int pipefd[2], length;
if (pipe(pipefd))
perror("Failed to create pipe");
pid_t pid = fork();
char path[MAX];
if (pid == 0) {
// NOTE/BUG: no need to close before dup2
#if 0
close(1); // close the original stdout
#endif
dup2(pipefd[1], 1); // duplicate pipfd[1] to stdout
close(pipefd[0]); // close the readonly side of the pipe
close(pipefd[1]); // close the original write side of the pipe
execvp(args[0], args); // finally execute the command
exit(1);
}
if (pid < 0) {
perror("fork");
exit(1);
}
dbgprt("ls_loop: PARENT\n");
close(pipefd[1]);
while (length = read(pipefd[0], path, MAX - 1)) {
dbgprt("ls_loop: DATAREAD %s\n",dbgstr(path,length));
if (send(new_socket, path, length, 0) != length) {
perror("Failed");
}
memset(path, 0, MAX);
}
close(pipefd[0]);
}
dbgprt("ls_loop: EXIT stop=%d\n",stop);
}
void *
server_socket_ls(void *arg)
{
tid = "ls";
dbgprt("lsmain: ENTER\n");
do {
server_arg *s = (server_arg *) arg;
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
dbgprt("lsmain: SOCKET\n");
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
int enable = 1;
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(int)) < 0) {
perror("error");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(s->portNum);
dbgprt("lsmain: BIND prtNum=%u\n",s->portNum);
if (bind(server_fd, (struct sockaddr *) &address, sizeof(address))
< 0) {
perror("bind failed");
}
dbgprt("lsmain: LISTEN\n");
if (listen(server_fd, 3) < 0) {
perror("listen");
}
while (1) {
if ((new_socket = accept(server_fd, (struct sockaddr *) &address,
(socklen_t *) & addrlen)) < 0) {
perror("accept");
}
dbgprt("lsmain: ACCEPTED\n");
int stop = ls_loop(new_socket);
close(new_socket);
if (stop) {
dbgprt("lsmain: STOP\n");
break;
}
}
} while (0);
dbgprt("lsmain: EXIT\n");
return (void *) 0;
}
void *
server_socket_file(void *arg)
{
tid = "file";
dbgprt("file: ENTER\n");
server_arg1 *s1 = (server_arg1 *) arg;
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
int enable = 1;
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int))
< 0) {
perror("error");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(s1->portNum);
dbgprt("file: BIND portNum=%u\n",s1->portNum);
if (bind(server_fd, (struct sockaddr *) &address, sizeof(address)) < 0) {
perror("bind failed");
}
if (listen(server_fd, 3) < 0) {
perror("listen");
}
if ((new_socket = accept(server_fd, (struct sockaddr *) &address,
(socklen_t *) & addrlen)) < 0) {
perror("accept");
}
printf("Server Connected\n");
}
int
main(int argc, char const *argv[])
{
tid = "main";
tsczero = tscgetf();
server_arg *s = (server_arg *) malloc(sizeof(server_arg));
server_arg1 *s1 = (server_arg1 *) malloc(sizeof(server_arg1));
pthread_t id_1;
pthread_t id_2;
pthread_t id_3;
xfdbg = fopen("debug.txt","w");
setlinebuf(xfdbg);
if (pthread_create(&id_3, NULL, terminal_thread, NULL) != 0) {
perror("pthread_create");
}
// NOTE/BUG: this port (or the one below) doesn't match the client code
// port of 5126
s->portNum = 9191;
pthread_create(&id_1, NULL, server_socket_ls, s);
s1->portNum = 6123;
if (0)
pthread_create(&id_2, NULL, server_socket_file, s1);
pthread_join(id_1, NULL);
if (0)
pthread_join(id_2, NULL);
pthread_join(id_3, NULL);
// NOTE/BUG: pthread_exit in main thread is wrong
#if 0
pthread_exit(0);
#else
fclose(xfdbg);
return 0;
#endif
}
這是除錯輸出:
[0.000170689/ ls] lsmain: ENTER
[0.000240819/ ls] lsmain: SOCKET
[0.000281554/ ls] lsmain: BIND prtNum=9191
[0.000207250/term] term: PROMPT
[0.000312276/term] term: FGETS
[0.000372488/ ls] lsmain: LISTEN
[2.367264029/term] term: COMMAND '.l'
[2.367295218/term] open_remote: ENTER ip='127.0.0.1' port=9191
[2.367346382/term] term: port=9191
[2.367434666/term] open_remote: EXIT sock=6
[2.367439573/ ls] lsmain: ACCEPTED
[2.367455805/ ls] ls_loop: ENTER new_socket=5
[2.367467511/ ls] ls_loop: COMMAND 'ls'
[2.367636543/ ls] ls_loop: PARENT
[2.369013467/ ls] ls_loop: DATAREAD 'debug.txt{0A}fix1{0A}fix1.c{0A}orig{0A}orig.c{0A}orig.txt{0A}out{0A}'
[2.369206789/term] term: PROMPT
[2.369222828/term] term: FGETS
[20.551357125/term] term: COMMAND 'exit'
[20.551378790/term] term: SENDEXIT
[20.551452423/term] term: EXIT
[20.551586028/ ls] ls_loop: COMMAND 'exit'
[20.551609143/ ls] ls_loop: EXIT/COMMAND
[20.551615857/ ls] ls_loop: EXIT stop=1
[20.551649125/ ls] lsmain: STOP
[20.551656969/ ls] lsmain: EXIT
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/479879.html
上一篇:一個文本由套接字不停地發送,在一個回圈中,我希望它只發送一次
下一篇:并發服務器執行緒-給出系結錯誤
