C 套接字通信与字符串连接

C 套接字通信与字符串连接,c,rpc,C,Rpc,亲爱的各位, 我正在尝试实现一个客户机-服务器模型,客户机尝试接受用户输入,将消息发送到服务器,然后服务器追加“从服务器回显:”+(客户机消息)并发送回服务器,但我使用以下代码未成功,有人能帮我一个忙吗?我在这里花了很多时间:( 客户 /* * Usage: sender [host] * * General description of code: * (1) Create a local socket, specifying domain and protocol *

亲爱的各位, 我正在尝试实现一个客户机-服务器模型,客户机尝试接受用户输入,将消息发送到服务器,然后服务器追加“从服务器回显:”+(客户机消息)并发送回服务器,但我使用以下代码未成功,有人能帮我一个忙吗?我在这里花了很多时间:(

客户

  /*
 * 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);
}
/*
*用法:发送方[主机]
*
*代码的一般说明:
*(1)创建本地套接字,指定域和协议
*(2)设置远程地址
*(3)连接到它
*(4)向服务器发送/接收数据
*(5)紧密连接
*/
#包括
#包括
#包括
#包括
#包括
#定义端口5667
主(argc、argv)
int-argc;
char*argv[];
{
int-s;
结构主机*远程设备;
远程地址中的结构sockaddr\u;
char-ch[40];
如果(argc!=2){
printf(“用法:发送方主机名”);退出(1);
}
/*(1)创建套接字*/
if((s=socket(AF\u INET,SOCK\u STREAM,0))<0){
perror(“无法创建发送_套接字”);退出(1);
}
/*(2)分配远程地址*/
远程地址sin家庭=AF网络;
远程地址sin\u端口=htons(端口);
if((remote_ent=gethostbyname(argv[1]))==NULL){
perror(“无法获取远程主机地址”);退出(1);
}
b复制(远程内容->地址列表[0],
&远程地址:sin地址,远程地址->h\U长度);
/*(3)连接到远程插座*/
if(连接(s,&remote\u addr,sizeof(remote\u addr))<0){
perror(“无法连接到远程地址”);退出(1);
}
/*(4)通过插座发送/接收数据*/
while((get(ch))!=“){
如果(写入(s,ch,40)<0){
perror(“写入错误”);退出(1);
}
读(s,ch,1);
看跌期权(ch);
}
/*(5)关闭并退出*/
关闭;/*同时关闭远程插座*/
出口(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);
}
/*
*接收机c
*
*接收器(服务器)一对套接字的一半。
*注意:接收器已经是多线程的!
*/
#包括
#包括
#包括
#包括
#包括
#通过Kei定义端口5667/**/
main(){
国际标准,新标准;
国际远程地址;
本地地址、远程地址中的结构sockaddr\u;
char-ch[40];
char*ch2=“从服务器回显:”;
/*(1)创建套接字*/
if((s=socket(AF\u INET,SOCK\u STREAM,0))<0){
perror(“无法创建s”);
出口(1);
}
bzero(&local_addr,sizeof(local_addr));
/*(2)设置地址*/
本地地址sin家庭=AF\u INET;
local_addr.sin_port=htons(port);/*port#,不需要IP地址*/
/*(3)将本地地址绑定到此套接字*/
if(绑定本地地址,大小(本地地址))<0{
perror(“无法将套接字绑定到本地地址”);退出(1);
}
/*(4)等待连接(仅允许1个挂起)*/
如果(听(s,1)<0){
perror(“侦听失败”);退出(1);
}
而(1){/*等待连接,recv和reply*/
/*(5)接受连接*/
如果((新地址=接受(远程地址和远程地址))0){
strcat(ch2,ch);
如果(写入(新的,ch2,40)<0){
perror(“写入错误”);退出(1);}
将(ch);/*放在屏幕上*/
}
关闭(纽约);
}
/*(7)关闭并退出*/
关闭(s);;
出口(0);
}

您的程序有几个问题,我可以马上看到

  • receiver.c
    中,您使用字符串文本作为第一个参数调用
    strcat()
    ——尝试修改字符串文本会导致未定义的行为。即使您成功地修改了字符串文本,您也不会在再次执行循环之前重置它——您的输出不会像您想要的那样

  • sender.c
    中,您试图将字符串与
    =
    运算符(调用
    get()
    的结果)进行比较。这不起作用。请使用
    strcmp()

  • 不要使用
    gets()
    -它很容易出现缓冲区溢出。
    fgets()
    可以安全使用-试试看

  • 您的
    sender.c
    程序在尝试从服务器获取回显时仅读取1个字节。您需要尝试接收要获取的整个字符串


  • 虽然你没有说你遇到了什么样的问题,但有一个问题是相当明显的:

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

    “但我不成功”是什么意思?错误消息?崩溃?糟糕的输出?我认为
    strcmp()
    调用也需要
    \n
    ,因为
    fgets()
    将把它包含在返回的字符串中。@Carl Norum:不——这不是
    strtok
    的“奇怪但有用的目的”——去掉尾部“\n”是的,我理解,但是调用在
    while
    循环体中。循环将如何结束?
    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) { 
    // ...