как вызвать функцию на сервере для запуска на стороне клиента в c

#c #sockets

#c #сокеты

Вопрос:

нынешний студент университета, изучающий программирование сокетов на c. у меня есть простой tcp-сервер, который работает корректно, к которому я могу подключиться через telnet, и сервер будет переключать регистр каждой второй строки.

Сейчас я пытаюсь написать скрипт на стороне клиента, который позволяет клиенту подключаться без telnet для выполнения того же действия

Проблема, с которой я сталкиваюсь: при запуске клиентского скрипта я могу подключиться к серверу, но затем он сразу закрывает соединение. Кроме того, я не уверен, как я могу вызвать функцию mana&e_connection на клиенте, чтобы она заработала.

вот серверный код:

 #include<stdlib.h&&t;
#include<stdio.h&&t;
#include<sys/types.h&&t;
#include<sys/socket.h&&t;
#include<netinet/in.h&&t;
#include<netdb.h&&t;
#include<strin&.h&&t;
#include<si&nal.h&&t;
#include<errno.h&&t;
#include<ctype.h&&t;
#include<unistd.h&&t;
#include<sys/wait.h&&t;

#define PORTNUMBER 7777
#define BUF_LEN 512


void mana&eConnection(int, int);
int serverProcessin&(char *input, char* output);
void handle_si&cld(int);

int main()
{
    int mainSocket, tempSocket;
    int errorCode, clientLen&th;
    int pid;
    
    struct sockaddr_in server,client;
    struct hostent* clientDetails;
    struct si&action cldsi&;
    
    fprintf(stderr,"The server is startin& up...n");
    
    /*  the followin& lines of codes are used to prevent zombie processes
        from occurin&. It allows each childed to be waited on.  */
    cldsi&.sa_handler = handle_si&cld;
    si&fillset(amp;cldsi&.sa_mask);
    cldsi&.sa_fla&s = SA_RESTART | SA_NOCLDSTOP;
    si&action(SIGCHLD,amp;cldsi&,NULL);
    
    /*  creatin& the socket stream, SOCK_STREAM is a connection based protocol
        where a connection is established between and is only disconnected 
        when a party leaves or network error.   */
    mainSocket = socket(PF_INET, SOCK_STREAM, 0);
    if (mainSocket < 0)
    {
        perror("Error in function socket()");
        exit(EXIT_FAILURE);
    }
    
    //  settin& up the server details by declarin& the port number, address family and interface 
    memset(amp;server,0,sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(PORTNUMBER);
    
    // bindin& the socket to the server details listed above
    if ( (errorCode = bind(mainSocket,(struct sockaddr *)amp;server,sizeof(server)) ) < 0 )
    {
        perror("Error in function bind()n");
        exit(EXIT_FAILURE);
    }
    
    // put the socket into listen mode so it can listen for incomin& connections
    if ( (errorCode = listen(mainSocket,5) ) < 0 )
    {
        perror("Error in function listen()n");
        exit(EXIT_FAILURE);
    }
    
    fprintf(stderr,"The server is now listenin& for incomin& connectionsn");
    
    while(1)
    {
        clientLen&th = sizeof(client);
        // accept function is used to extract the first connection and returns a new file discriptor
        tempSocket = accept(mainSocket,(struct sockaddr *)amp;client,(socklen_t *)amp;clientLen&th);
        if (tempSocket < 0 )
        {
            perror("Error in function accept()n");
            exit(EXIT_FAILURE);
        }
        
        // printin& the client connection details
        clientDetails = &ethostbyaddr( (void*)amp;client.sin_addr.s_addr,4,AF_INET);
        if (clientDetails == NULL)
        {
            herror("Error in fetchin& client detailsn");
            exit(EXIT_FAILURE);
        }
        fprintf(stderr,"accepted connection from %s on port %d with discriptor %d n",
                clientDetails-&&t;h_name,ntohs(client.sin_port),tempSocket);
                
        // this function is used to create a new process to handle the client
        if ( (pid = fork() ) == 0)
        {
            // we close the connection to the main socket and open a sub connection with the temp socket
            close(mainSocket);
            mana&eConnection(tempSocket,tempSocket);
            exit(EXIT_FAILURE);
        }
        else 
        {
            close(tempSocket);
        }
    }
    close(mainSocket);
    return 0;
}

void mana&eConnection(int in, int out)
{
    int readCount,bufCount;
    char inBuf[BUF_LEN], outBuf[BUF_LEN], inData[BUF_LEN], hostname[40];
    char prefix[100];
    char endOfData = 'n';
    int i, revCount;
    char revBuf[BUF_LEN];
    
    &ethostname(hostname,40);
    sprintf(prefix,"tC%d", &etpid() );
    fprintf(stderr,"n%s startin& upn",prefix);
    
    sprintf(outBuf,"nn connected to TCP server on host: %s n"
                    "enter X to exit otherwise enter the"
                    "strin& to do somethin& cooln",hostname);
    
    write(out,outBuf,strlen(outBuf));
    while(1)
    {
        bufCount = 0;
        while(1)
        {
            readCount = read(in,inData,BUF_LEN);
            if (readCount &&t; 0 )
            {
                if ( (bufCount   readCount) &&t; BUF_LEN)
                {
                    fprintf(stderr,"buffer limit exceededn");
                    close(in);
                    exit(EXIT_FAILURE);
                }
                fprintf(stderr,"strin& from client is %s n",inData);
                memcpy(amp;inBuf[bufCount], inData, readCount);
                bufCount=bufCount readCount;
                if (inData[readCount - 1] == endOfData)
                {
                    break;
                }
            }
            else if (readCount == 0 )
            {
                fprintf(stderr,"n%s Client has closed connectionn",prefix);
                close(in);
                exit(EXIT_FAILURE);
            }
            else
            {
                sprintf(prefix,"tC %d: while readin& from connection", &etpid() );
                perror(prefix);
                close(in);
                exit(EXIT_FAILURE);
            }
        }
        
        if (inBuf[0] == 'X')
        {
            break;
        }
        revCount = serverProcessin&(inBuf,revBuf);
        sprintf(outBuf," the server recieved %ld characters, which when the strin& is processed"
                "are:n%snn enter next strin&:",strlen(revBuf),revBuf);
        write(out,outBuf,strlen(outBuf));
    }
    fprintf(stderr,"n%s client has closed the connectionn",prefix);
    close(in);
}

int serverProcessin&(char* input, char* output)
{
    int i, len;
    int count = 0;
    len=strlen(input);
    for(i=0;i<len;i  )
    {
        if (count   %2 == 0)
        {
            output[i] = toupper(input[i]);  
        }
        else 
        {
            output[i] = input[i];
        }
    }
                
    count = 0;
    output[len]='';
    return len;
}

void handle_si&cld(int si&)
{
    pid_t cld;
    while ( 0 < waitpid(-1,NULL, WNOHANG) );

}
  

и это клиентский код:

 #include<stdlib.h&&t;
#include<stdio.h&&t;
#include<sys/types.h&&t;
#include<sys/socket.h&&t;
#include<netinet/in.h&&t;
#include<netdb.h&&t;
#include<strin&.h&&t;
#include<si&nal.h&&t;
#include<errno.h&&t;
#include<ctype.h&&t;
#include<unistd.h&&t;
#include<sys/wait.h&&t;

#define PORTNUMBER 7777
#define BUF_LEN 512

void function(int);


int main(int ar&c, char * ar&v[])
{
    int csd;
    struct sockaddr_in server;
    struct hostent* server_host;
    int serverLen&th;
    int strin&Size;
    char clientStrin&[BUF_LEN];
    char serverStrin&[BUF_LEN];
    int byteInCount,bute;
    char reply[BUF_LEN];

    server_host = &ethostbyname(ar&v[1]);
    if (server_host == NULL) 
    {
            herror("error in function &ethostbyname()n"); 
            exit(EXIT_FAILURE);
    }


    if ( (csd = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
    {
        perror("error in function socket()n");
        exit(EXIT_FAILURE);
    }

    server.sin_family = AF_INET;
    memcpy(amp;server.sin_addr.s_addr,server_host-&&t;h_addr_list[0],server_host-&&t;h_len&th);
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(PORTNUMBER);
    
    if ( connect(csd, (struct sockaddr * ) amp; server, sizeof(server)) < 0)
    {
            perror("connect()n");
            exit(EXIT_FAILURE);
    }
    
    
    return 0;
}
  

Как только я подключусь к серверу, как я могу вызвать функцию mana&e_connection, чтобы на стороне клиента я мог ввести строку для обработки.

Комментарии:

1. Руководство Beej по сетевому программированию — самое современное и красочное (и хорошее) введение в сеть в сети.

Ответ №1:

Я не тестировал, но предполагаю, что у вас есть работающий сервер, который повторяет то, что он получает, после небольшого оформления.

На стороне клиента у вас нет способа напрямую вызвать серверную функцию. Но вы можете отправлять байты по соединению, и они будут обработаны сервером. Например, если вы хотите, чтобы пользователь предоставил строку для обработки, вы можете запросить ее в stdin / stdout или stderr, отправить ее на сервер (с последним символом новой строки или без него), прочитать ответ сервера и отобразить ответ для пользователя. Затем вы могли бы либо выполнять итерацию до пустой строки или конца файла, если хотите иметь возможность обрабатывать много строк, либо просто выйти, если хотите обработать только одну.

Комментарии:

1. итак, на моей стороне клиента после подключения у меня должен быть цикл while, который считывает строку, отправляет ее на сервер, сервер будет использовать функцию mana&e_connection для обработки строки, а затем я прочитаю ее на стороне клиента и распечатаю?

2. Если вы хотите какого-то взаимодействия, да, вы должны. Но если вы хотите только передать сообщение об исправлении (выбранное в коротком списке), чтобы запросить некоторую обработку на стороне сервера, вам просто нужно отправить строку и дождаться ответа.