2011-03-13 2 views
0

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

Client

/* 
* 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

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

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

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

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

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

1

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

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) { 
// ... 
+0

Я думаю, что вызов 'strcmp()' нуждается в '\ n', так как' fgets() 'собирается включить его в возвращаемую строку. –

+0

@Carl Norum: Нет - это «странная, но полезная цель для« strtok »- удаление дескриптора« \ n »с прочитанной строки, если она присутствует. –

+0

Да, я понимаю это, но этот вызов * внутри * тело цикла while. Как цикл кончится? –

Смежные вопросы