клиентский сервер с программой - PullRequest
0 голосов
/ 03 марта 2010

Я написал программу клиента и сервера c, которую я взял из примера кода.

Я хочу написать итеративную клиентскую и серверную программу, то есть после того, как клиент отправит строку, сервер напечатает эту строку и затем отправит обратно строку клиенту

затем клиент печатает строку, введенную сервером, и так далее до тех пор, пока клиент не введет «exit» для выхода.

Я изменил код, согласно которому клиент и сервер являются итеративными

также, если клиент введет «exit», программа завершит работу

Но у меня есть вопрос, я не знаю, как заставить клиента получать строку, которая вводится сервером, я могу только заставить сервер получать строку клиента

Пожалуйста, не стесняйтесь давать подсказки

Большое спасибо!

мой код

client.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <winsock2.h>

#define SA struct sockaddr
#define S_PORT 4321
#define BufferStoreLEN 1024

void errexit(const char *format, ...)
{
        va_list args;
        va_start(args, format);
        vfprintf(stderr, format, args);
        va_end(args);
        WSACleanup();
        exit(1);
}

int main(int argc, char **argv)
{
        WSADATA wsadata;
        SOCKET sockfd, listenfd, connfd;
        int i, n, q, len, alen, out;
        char str[BufferStoreLEN+1];
        char cmp[] = "exit";
        char* BufferStore;
        struct sockaddr_in servaddr, cliaddr;

        if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
                errexit("WSAStartup failed\n");

        if (argc != 2)
                errexit("wrong arg");

        if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET )
                errexit("socket error: error number %d\n", WSAGetLastError());

        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(S_PORT);
        if ( (servaddr.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE)
                errexit("inet_addr error: error number %d\n", WSAGetLastError());

        if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR)
                errexit("connect error: error number %d\n", WSAGetLastError());

        do {
                printf("Input: ");
                scanf("%s", str);
                out = htonl(strlen(str));
                BufferStore = malloc(strlen(str));
                for( i=0; i<strlen(str); i++)
                        BufferStore[i] = str[i];
                out = send(sockfd, BufferStore, strlen(str), 0);
/*              
                if ( strcmp( cmp, str ) != 0 )
                {
                        printf("Server's response:\n");
                        n = recv(connfd, BufferStore, BufferStoreLEN, 0);

                        while (n > 0) {
                                BufferStore[n] = '\0';
                                printf("%s\n", BufferStore);
                                n = recv(connfd, BufferStore, BufferStoreLEN, 0);
                        } 
                }*/
        }while(strcmp(cmp,str)!=0);

        closesocket(sockfd);
        WSACleanup();
        free(str);
        free(BufferStore);
        return 0;
}

server.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <winsock2.h>
#include <Windows.h>
#define SA struct sockaddr
#define MAXLINE 4096
#define S_PORT 4321
#define BufferStoreLEN 1024

void errexit(const char *format, ...)
{
        va_list args;
        va_start(args, format);
        vfprintf(stderr, format, args);
        va_end(args);
        WSACleanup();
        exit(1);
}

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

        WSADATA wsadata;
        SOCKET listenfd, connfd;
        SOCKET sockfd;
        int number, out;
        int i, n, q, alen;
        struct sockaddr_in servaddr, cliaddr;
        char BufferStore[BufferStoreLEN+1];
        char* Store;
        char str[BufferStoreLEN+1];
        int flag = 1;

        if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
                errexit("WSAStartup failed\n");

        listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (listenfd == INVALID_SOCKET)
                errexit("cannot create socket: error number %d\n", WSAGetLastError());

        memset(&servaddr, 0, sizeof(servaddr)); 
        servaddr.sin_family      = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port        = htons(S_PORT);

        if (bind(listenfd, (SA *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR)
                errexit("can't bind to port %d: error number %d\n", S_PORT, WSAGetLastError());

        if (listen(listenfd, 5) == SOCKET_ERROR)
                errexit("can't listen on port %d: error number %d\n", S_PORT, WSAGetLastError());

        if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET )
                errexit("socket error: error number %d\n", WSAGetLastError());

        for ( ; ; ) 
        {
                alen = sizeof(SA);
                connfd = accept(listenfd, (SA *) &cliaddr, &alen);
                if (connfd == INVALID_SOCKET)
                        errexit("accept failed: error number %d\n", WSAGetLastError());

                n = recv(connfd, BufferStore, BufferStoreLEN, 0);

                while (n > 0){
                        BufferStore[n] = '\0';
                        printf("%s\n", BufferStore);
                        printf("Input: ");
                        scanf("%s",str);
                        out = htonl(strlen(str));
                        Store = malloc(strlen(str));
                        for( q=0; q<strlen(str); q++)
                                Store[q] = str[q];
                        out = send(sockfd, Store, strlen(str), 0);
                        n = recv(connfd, BufferStore, BufferStoreLEN, 0);
                } 
                closesocket(sockfd);
                WSACleanup();
                free(str);
                free(BufferStore);
        }
}

Ответы [ 2 ]

0 голосов
/ 03 марта 2010

Одна вещь, которую важно понять о потоковых сокетах (SOCK_STREAM), заключается в том, что они предоставляют вам поток байтов (отсюда и название :-)), без каких-либо «границ пакетов».

В частности, если вы отправляете () 100 байт данных от клиента, сервер может вызвать recv () как

  • один вызов recv (), возвращающий 100 байтов
  • два recv () по 50 байт каждый
  • один recv () 90 байтов, за которым следуют 10 recv () с 1 байта
  • ... и т.д ...

Ваш код, по-видимому, предполагает, что то, что вы отправляете () на одном конце, будет доставлено за один вызов recv () на другом конце. Для небольших порций данных это может сработать, но это не то, на что вы можете / должны полагаться.

В общем, для выполнения сценария команда / ответ, который вы настраиваете, вам нужно, чтобы сервер мог распознать «это конец команды, я должен ответить сейчас». Например, если вы отправляете текстовые строки, вы можете использовать символ новой строки (\ n) в качестве маркера «конец команды».

Таким образом, сервер будет выполнять несколько вызовов recv () (каждый из которых добавляет в буфер), пока не увидит \ n (или ошибку), а затем отправит ответ обратно; клиент будет делать нечто подобное при чтении ответа.

0 голосов
/ 03 марта 2010

Ваш сервер работает в бесконечном цикле, поэтому, чтобы иметь возможность отправлять данные, которые вводятся в серверное приложение, в клиентское приложение, вам необходимо прочитать пользовательский ввод в другом потоке, а затем отправить его пользователю, поскольку бесконечный цикл в настоящее время блокирует текущий поток.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...