套接字通信和字符串连接

时间:2011-03-13 05:40:08

标签: c rpc

亲爱的,     我正在尝试实现一个客户端 - 服务器模型,客户端尝试接受用户输入,将消息发送到服务器,然后服务器追加“Echoed from server:”+(客户端的消息)并发送回服务器,但我不使用以下编纂成功,是否有人可以帮我一个忙?我在这里度过了很多时间:(

客户端

  /*
 * 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 个答案:

答案 0 :(得分:1)

你的程序有几个我可以立即看到的问题。

  1. receiver.c中,您使用字符串文字作为第一个参数调用strcat() - 尝试修改字符串文字会导致未定义的行为。即使你确实成功修改它,你也不会在重新循环之前重置它 - 你的输出看起来不像你想要的那样。

  2. sender.c中,您尝试将字符串与==运算符(gets()调用的结果和".")进行比较。那不行。使用strcmp()

  3. 不要使用gets() - 它容易出现缓冲区溢出。 fgets()可以安全使用 - 请尝试使用。

  4. 当您尝试从服务器获取回显时,您的sender.c程序只读取1个字节。您需要尝试接收想要返回的整个字符串。

答案 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) { 
// ...