2012-04-23 5 views
-1

次のプログラムでは、サーバーを介して読み書きができます。しかし、書き込みを実行する()するとき、それは余分な文字をプリントアウトソケットから文字列を読み取っているときに、書き込みで余分な文字が出力される

// this a server program 
#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <unistd.h>    // for ssize_t data type 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <sys/un.h> 
#include <arpa/inet.h> 
#include <errno.h> 
#include <wait.h> 

#define LISTENQ  (24) /* Backlog for listen() */ 
#define MAXBUFFSIZE 12 

// Read in characters. Increase memory if we run out of space. 
char *stdin_line(int conn) 
{ 
    int rr=0, size=0, cap = MAXBUFFSIZE; 
    char *str_ptr;//, oc; 
    char buff[MAXBUFFSIZE]; 

    // allocate some memory for the pointer first 
    str_ptr = (char *) malloc(cap * sizeof(char)); 
    assert(str_ptr != NULL); 
    // start reading from socket 
    rr=read(conn,buff,MAXBUFFSIZE)) > 0) 
     if(rr > 0){ 
    str_ptr = buff; 
    size = MAXBUFFSIZE; 
    } 
    if(rr == -1) printf("Error (stdin_line): %s/n",strerror(errno)); 

    return str_ptr; 
} 


void daemonize(void){ 
    pid_t pid, sid=0; 
    // fork off process 
    pid = fork(); 
    // failure 
    if(pid < 0){ 
    printf("Error (fork<0): %s\n",strerror(errno)); 
    exit(1); 
    } 
    // exit parent process 
    if(pid > 0){ 
    printf("Error (fork>0): %s\n",strerror(errno)); 
    exit(0); 
    } 
    // change file mode mask 
    umask(0); 

// open log file for daemon debug information. OR as per requirements of hw4 

    // create new Session ID for child process 
    setsid(); 
    if(sid < 0){ 
    printf("Error (setsid<0): %s\n",strerror(errno)); 
    exit(1); 
    } 
    // exit parent process 
    if(sid > 0){ 
    printf("Error (setsid>0): %s\n",strerror(errno)); 
    exit(0); 
    } 

    // change working directory to safe directory (one which is always there) 
    if(chdir("/") < 0){ 
    printf("Error (chdir): %s\n",strerror(errno)); 
    exit(1); 
    } 

} 


int main(void) { 

    int lstn_sock, conn_sock; 
    struct sockaddr_in my_serv; 
    short int pnum = 4080; 
    ssize_t wnum; 
    char *rstr=NULL; 

    // create listening socket 
    if((lstn_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 
    printf("Error (socket): %s\n",strerror(errno)); 
    exit(1); 
    } 

    // initialize socket address 
    memset(&my_serv, 0, sizeof(my_serv)); 
    my_serv.sin_family = AF_INET; 
    my_serv.sin_addr.s_addr = INADDR_ANY; 
    my_serv.sin_port = htons(pnum); 

    // associate address with socket. 
    if(bind(lstn_sock, (struct sockaddr *) &my_serv, sizeof(my_serv)) < 0){ 
    printf("Error (bind): %s\n",strerror(errno)); 
    exit(1); 
    } 
    // start listening to socket 
    if(listen(lstn_sock, LISTENQ) < 0){ 
    printf("Error (listen): %s\n",strerror(errno)); 
    exit(1); 
    } 
    // make it a daemon 
    daemonize(); 

    // work in the background 
    while(1){ 
    // retrieve connect request and connect 
    if((conn_sock = accept(lstn_sock, NULL, NULL)) < 0){ 
     printf("Error (accept): %s\n",strerror(errno)); 
     exit(1); 
    } 

    rstr = stdin_line(conn_sock); 

    if((wnum=write(conn_sock,rstr,strlen(rstr))) <= 0){ 
     printf("Error (write: rstr): %s\n",strerror(errno)); 
     exit(1); 
    } 

    // close connected socket 
    if(close(conn_sock) < 0){ 
     printf("Error (close): %s\n",strerror(errno)); 
     exit(1); 
    } 
    } 


return 0; 

} 

@ubuntu:$ ./my_code
@ubuntu:$ののtelnet localhostの4080

出力::: 1をしようと
。 ..
試行127.0.0.1 ..
ローカルホストに接続しました。
エスケープ文字は '^]'です。外部ホストによって閉じ
J
J
DHK
接続。

最初の「j」はユーザー(私)によって入力され、2番目の「j」はサーバーによってエコーされます。なぜ「dhk」と「9」の文字が得られますか?

答えて

1

受信した実際のデータ量を無視すると、rrとなり、文字列全体が印刷されるためです。

rr=read(conn,buff,MAXBUFFSIZE)) > 0) 
    if(rr > 0){ 
str_ptr = buff; 
size = MAXBUFFSIZE; 
} 

また、この単なるコピーポインタと文字列ではなく、それ自体として、このstr_ptr = buff;を行うべきではありません。 buffはスタックに割り当てられているため、関数が返っても無効になる可能性があります。

+0

ありがとう@ Tibor。実際には、read()から一度に1文字を読み込み、最後にヌル文字を代入して文字列全体を終了させることを計画しています。それが動作することを願って! – jdek

関連する問題