Мне необходимо разработать урезанную версию онлайн-среды IDE.Это будет следовать архитектуре клиент-сервер.На стороне клиента будет три команды:
- CREATE
- RUN
- QUIT
Когда клиент выбирает «создать», команда отправляется на сервер.Сервер откроет окна.Первое окно будет текстовым редактором, в котором пользователь сможет написать код.Второе окно будет действовать как автоматический анализатор, который будет анализировать программу, которую пользователи написали в первом окне.Серверная сторона будет читать пользовательскую программу с интервалом в 1 секунду и анализировать программу, используя Lex и yacc.О любой ошибке, обнаруженной в программе, следует сообщать в окне 2. Если ошибок нет, в окне будет просто указано «Нет ошибок».
Я сделал до синтаксического анализа части.Но я не мог понять, как открыть терминал из программы и вывести ошибку на этот терминал.Я публикую свой код здесь.
СТОРОНА СЕРВЕРА:
#include<stdio.h>
#include<stdlib.h>
#include<string.h> // This is for string related call.
#include<errno.h> // This is for error handling.
#include<limits.h> // this is for different type limit checking.
#include<ctype.h> // This is for different type checking.
#include<fcntl.h> // This is for unblocking socket.
#include<unistd.h> // this is for different type typical system call.
#include<sys/socket.h> // This header file defines miscellaneous socket related constant, types, and function.
#include<sys/types.h> // This header file defines miscellaneous types
#include<sys/sem.h> // This header file defines semaphores related types, function.
#include<sys/wait.h> // This header file defines blocking and wait related types and function.
#include<sys/ipc.h> // This header file defines mainly interprocess communication related structures.
#include<netinet/in.h> // This header file defines system parameter related to address.
#include<arpa/inet.h> // This header file defines different types macros .
#include<time.h> // This header file is included for getting times.
#include<signal.h>
#include<netdb.h>
#include<sys/shm.h> // This header file is included for shared memory .
#define PORT "5000" // This is the port server will be listening on
#define MAX 4096
#define NAZMUL
extern void parse(FILE*,FILE*);
int listener; // Server will be listening on this socket id.
/*.....................This function convert the IP address................................*/
void *convert(struct sockaddr *sa)
{
if(sa->sa_family == AF_INET)
return &(((struct sockaddr_in *)sa)->sin_addr);
return &(((struct sockaddr_in6 *)sa)->sin6_addr);
}
/*.........................................................................................*/
/*...............We are handling SIGINT SIGNAL here..........................................*/
void sigint_handler(int sig)
{
int nbytes;
char buffer[MAX];
strcpy(buffer, "quit");
#if hi
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) < 0)
{
if(nbytes == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{
perror("SERVER:");
close(new_fd);
close(listener);
exit(EXIT_FAILURE);
}
}
close(listener);
close(new_fd);
#endif
exit(EXIT_SUCCESS);
}
/*............................................................................................*/
/*.......................We are handling SIGCHLD signal here..................................*/
void sigchild_handler(int sig)
{
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
/*..............................................................................................*/
/*...........................We are generating random number here...............................*/
int main()
{
int yes = 1; // this for setsockopt()
int status; // this is for holding return value of getaddrinfo()
int proces_id_gedit; // this will hold return value of fork()
int flags; // this for fcntl() call
char file_name[128]; // This is for saving filename.
char command[128],filenameout[128];
FILE *fp, *output_fp;
int create_flag = 0; // To check whether create command came or not
char *line = NULL;
size_t length = 0;
ssize_t nread;
struct sigaction for_sigint, for_sigchild; // these struct, we have to pass to sigaction()
char buffer[MAX]; // this will be used in send(), recv()
int nbytes; // This will hold return value of send(), recv()
int new_fd; // newly accept()ed socket descriptor.
struct sockaddr_storage client_addr; //it will hold client socket address.
char client_IP[INET6_ADDRSTRLEN]; // It will hold the ip address of client ip address.
socklen_t addr_len; // It will hold length of client ip address.
/*................GET us an successful socket and bind it...........................................*/
struct addrinfo hints, *ref, *p;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if((status = getaddrinfo(NULL, PORT, &hints, &ref)) != 0)
{
fprintf(stderr, "SERVER: getaddrinfo:%s\n",gai_strerror(status) );
exit(EXIT_FAILURE);
}
for(p = ref; p != NULL; p = p->ai_next)
{
if((listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
continue;
}
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("SERVER:");
exit(EXIT_FAILURE);
}
/*....Setting the socket in non-blocking mode...*/
if ((flags = fcntl(listener, F_GETFL, 0)) < 0)
{
perror("SERVER(flags = fcntl):");
continue;
}
if (fcntl(listener, F_SETFL, flags | O_NONBLOCK) < 0)
{
perror("SERVER( fcntl):");
continue;
}
/*..............................................*/
if(bind(listener, p->ai_addr, p->ai_addrlen) == -1)
{
continue;
}
break; // we get successfull socket and bind, so we do not need to traverse anymore.
}
if(p == NULL) //checking whether we get a successful binding socket or not
{
fprintf(stderr, "we did not get successful binding socket\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(ref);
/*..................we are handling here SIGINT SIGNAL....................................*/
for_sigint.sa_handler = sigint_handler;
for_sigint.sa_flags = 0;
sigemptyset(&for_sigint.sa_mask);
if(sigaction(SIGINT, &for_sigint, NULL) < 0)
{
perror("SERVER(sigint):");
exit(EXIT_FAILURE);
}
/*............................................................................................*/
/*.......................We are handling SIGCHLD signal here.................................*/
for_sigchild.sa_handler = sigchild_handler;
for_sigchild.sa_flags = SA_RESTART;
sigemptyset(&for_sigchild.sa_mask);
if(sigaction(SIGCHLD, &for_sigchild, NULL) < 0)
{
perror("SERVER(SIGCHLD):");
exit(EXIT_FAILURE);
}
/*.............................................................................................*/
listen(listener, 5); // we are listening here.
printf("SERVER:We are waiting for connection......................................\n");
for(;;)
{
addr_len = sizeof(client_addr);
if((new_fd = accept(listener, (struct sockaddr *)&client_addr, &addr_len)) < 0) // we are accepting new connection here.
{
}
else
{
/*....Setting the socket in non-blocking mode...*/
if ((flags = fcntl(new_fd, F_GETFL, 0)) < 0)
{
perror("SERVER(flags = fcntl):");
continue;
}
if (fcntl(new_fd, F_SETFL, flags | O_NONBLOCK) < 0)
{
perror("SERVER( fcntl):");
continue;
}
/*..............................................*/
inet_ntop(client_addr.ss_family, convert((struct sockaddr *)&client_addr), client_IP, sizeof client_IP);
printf("SERVER: We got connection from %s\n",client_IP );
if( fork() == 0)
{
close(listener); // child process does not need this.
for(;;)
{
memset(buffer, 0, 4096);
if((nbytes = recv(new_fd, buffer, MAX, 0)) == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{
if(strcmp(buffer, "quit") == 0)
{
memset(buffer, 0, 4096);
strcpy(buffer, "quit");
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) < 0)
{
if(nbytes == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{
}
}
else
{
if(create_flag == 1)
{
remove(file_name);
remove(filenameout);
create_flag = 0;
}
printf("SERVER: Connection with client %d is closed\n",new_fd );
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
}
else if(strcmp(buffer, "create") == 0)
{
printf("create command came\n");
memset(buffer, 0, 4096);
strcpy(buffer, "we got create command");
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
sprintf(file_name, "%d.txt",getpid() );
sprintf(filenameout,"%dout.txt",getpid());
sprintf(command,"gedit %s",file_name);
signal(SIGCHLD, SIG_IGN);
if((proces_id_gedit= fork())== 0)
{close(new_fd);
system(command);
}
else
create_flag = 1;
}
else if(strcmp(buffer, "run") == 0)
{
printf("run command came\n");
memset(buffer, 0, 4096);
output_fp = fopen(filenameout, "r");
while((nread = getline(&line, &length, output_fp)) != -1)
{
strcat(buffer, line);
}
free(line);
fclose(output_fp);
//printf("%s\n",buffer );
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) == 0)
{
if(nbytes == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{
}
}
char temp[128];
sprintf(temp, "kill -9 %d",proces_id_gedit);
//printf("%s\n",temp );
system(temp);
remove(filenameout);
remove(file_name);
create_flag = 0;
}
else
{
#if nazmul
memset(buffer, 0, 4096);
strcpy(buffer, "you entered invalid command");
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) < 0)
{
if(nbytes == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{}
}
#endif
}
if(create_flag == 1)
{
sleep(1);
fp = fopen(file_name, "r");
output_fp=fopen(filenameout, "w");
if ( fp != NULL)
{
//printf("we are calling parse\n");
parse(fp, output_fp);
fclose(fp);
}
fclose(output_fp);
}
}
}/*..........................................END OF FOR LOOP OF EACH CLIENT HANDLING PROCESS................*/
}/*..............................................END OF FORK IF BLOCK...........................................*/
else
{
close(new_fd); // parent does not need this
continue;
}
}/*..................................................END OF ACCEPT ELSE BLOCK....................................*/
}/*......................................................END OF OF MAIN FOR LOOP.......................................*/
}/*..........................................................END OF MAIN BLOCK.........................................................*/
Я просто публикую здесь информацию о сервере.Это может быть большой код для прохождения.Вы можете ответить просто, не читая код.Я предполагал, что я запускаю и клиент и сервер на моей машине