Сокетная связь и цепочка строк - PullRequest
0 голосов
/ 13 марта 2011

Уважаемые все, я пытаюсь реализовать модель клиент-сервер, в которой клиент пытается принять ввод пользователя, отправить сообщение на сервер, а затем сервер добавляет «Отголосок с сервера» + (сообщение клиента) и отправляет обратно насервер, но я не пользуюсь следующими кодировками, кто-нибудь может сделать мне одолжение?Я провел здесь много времени: (

Клиент

  /*
 * Usage: sender [host]
 *
 * General description of code:
 *   (1) Create a local socket, specifying domain and protocol
 *   (2) Set up the remote address
 *   (3) Connect to it
 *   (4) Send/recv data to server
 *   (5) Close connection
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

#define PORT            5667    

main(argc, argv)
int argc;
char *argv[];
{
    int         s;
    struct hostent      *remote_ent;
    struct sockaddr_in  remote_addr;
    char  ch[40];

    if (argc != 2) {
        printf("usage: sender hostname \n"); exit(1);
    }

    /* (1) Create the socket */
    if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
        perror("Can't create send_socket"); exit(1);
    }

    /* (2) Assign the remote address */
    remote_addr.sin_family = AF_INET;
    remote_addr.sin_port = htons(PORT);

    if ((remote_ent = gethostbyname(argv[1])) == NULL) {
        perror("Can't get remote host address"); exit(1);
    }
    bcopy(remote_ent->h_addr_list[0],
        &remote_addr.sin_addr, remote_ent->h_length);

    /* (3) Connect to remote socket */
    if (connect(s, &remote_addr, sizeof(remote_addr)) < 0) {
        perror("Can't connect to remote address"); exit(1);
    }

    /* (4) Send /recv data thru socket */
    while ((gets(ch)) != ".") {
        if (write(s, ch, 40) < 0) {
            perror("write error"); exit(1); 
        }
        read(s, ch, 1);
        puts(ch);
    }

    /* (5) Close and exit */
    close(s); /* close remote socket as well */
    exit(0);
}

Сервер

   /*
 * receiver.c
 *
 * Receiver (server) half of a pair of sockets.
 * Note: receiver is already multi-threading! 
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

#define PORT        5667    /* by Kei */
main() {
    int         s, new_s;
    int         remote_addr_len;
    struct sockaddr_in  local_addr, remote_addr;
    char            ch[40];
    char     *ch2 = "Echoed from server:";

    /* (1) Create the socket */
    if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
        perror("Can't create s");
        exit(1);
    }

    bzero(&local_addr,sizeof(local_addr));

    /* (2) Set up the address */
    local_addr.sin_family = AF_INET;
    local_addr.sin_port   = htons(PORT); /* port#, no need of IP addr */

    /* (3) Bind local address to this socket */
    if (bind(s, &local_addr, sizeof(local_addr)) < 0) {
        perror("Can't bind socket to local address"); exit(1);
    }

    /* (4) Wait for a connection (only 1 pending allowed)*/
    if (listen(s, 1) < 0) {
        perror("listen failed"); exit(1);
    }

    while (1) { /* wait for connection, recv and reply */

    /* (5) Accept connection */
        if ((new_s = accept(s, &remote_addr, &remote_addr_len))<0) {
            perror("Can't accept connection"); exit(1);
        }

        /* IP-addr & port # of the remote socket */ 
            printf("remote IP: %d.%d.%d.%d\n", 
            remote_addr.sin_addr._S_un._S_un_b.s_b1, 
            remote_addr.sin_addr._S_un._S_un_b.s_b2, 
            remote_addr.sin_addr._S_un._S_un_b.s_b3, 
            remote_addr.sin_addr._S_un._S_un_b.s_b4);
            printf("remote port: %d\n", remote_addr.sin_port);

    /* (6) Exchange data. Socket is Bi-directional! */
        while (read(new_s, ch, 40) > 0) {
      strcat(ch2,ch);
            if (write(new_s, ch2, 40) < 0) {
                perror("write error"); exit(1); }

            puts(ch); /* put on screen */
        }
        close(new_s);
    }
    /* (7) Close and exit */
    close(s);
    exit(0);
}

Ответы [ 2 ]

1 голос
/ 13 марта 2011

Хотя вы еще не сказали, с какой проблемой вы сталкиваетесь, одна проблема довольно очевидна:

while ((gets(ch)) != ".") {
    if (write(s, ch, 40) < 0) {

Прежде всего, не используйте gets - это просто зло. Во-вторых, когда вы отправляете данные, вы хотите отправить только столько, сколько реально ввел пользователь, не обязательно все 40 байтов, выделенных для буфера. В-третьих, строки не являются нативным типом в C - ваше сравнение с "." фактически сравнивает два указателя. Поскольку у них никогда не будет одного и того же адреса, он никогда не вернет истину. Что-то вроде следующего должно быть хотя бы немного ближе:

while (fgets(ch, sizeof(ch), stdin) && strcmp(ch, ".\n")) {
    strtok(ch, "\n");    // the oddball but useful purpose for `strtok`.
    if (write(s, ch, strlen(ch))<0) { 
// ...
1 голос
/ 13 марта 2011

У ваших программ есть пара проблем, которые я вижу сразу.

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

  2. В sender.c, вы пытаетесь сравнить строки с оператором == (результат вызова gets() и ".").Это не сработает.Используйте strcmp().

  3. Не используйте gets() - он подвержен переполнению буфера.fgets() можно использовать безопасно - попробуйте вместо этого.

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

...