2017-06-03 16 views
-1

我有一個基本的服務器客戶端程序,我正在用C編寫,而且我遇到了有關字符串和串聯的問題。 基本上我有一些字符串(下面僅2的例子中),我必須投入其大小由下式確定的緩衝區:保持目標長度的字符串連接

total # of registered people * 33 

各字符串中的示例具有的長度比小得多緩衝區的長度。我想拼接後獲得這樣的事情:

  [0]   [32] 
people_list=Mark   Amy\0; 

其中馬克(其中第二個被插入)就在緩衝區(PEOPLE_LIST)的開始和艾米是32個字符距馬克的開始(我希望我已經說清楚了)。

這是因爲客戶端代碼給了我,我無法修改它。客戶端代碼獲取緩衝區並讀取第一個元素,然後跳轉到32個字符並再次讀取。 我從客戶端的printf的得到的輸出是這樣的:

connected to server 
Registered people: 
Mark 

,而我想這一點:

connected to server 
Registered people: 
Mark 
Amy 

的通信是通過套接字,這點我已經檢查落實,但如果你希望提出一些改變,我將不勝感激。

Server代碼:

#include <stdio.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <string.h> 
#include <pthread.h> 
#include <sys/socket.h> 
#include <sys/un.h> 
#include <errno.h> 
#define LENGTH 32 

struct person { 
    char name[LENGTH+1]; 
    struct person *next; 
    struct person *prev; 

}; 
struct person *p_head = NULL; 

void addPerson(char* name_p){ 
    struct person *new = (struct person*) malloc(sizeof(struct person)); 
    strcpy(new->name, name_p); 
    new->name[LENGTH]='\0'; 
    new->next=p_head; 
    new->prev=NULL; 
    p_head=new; 

} 

int main(){ 

    int fd_ser; 
    int fd_c; 
    int N=100; 
    char buf[N]; 
    int times=0; 
    char* path="tmp/sock"; 

    struct sockaddr_un sa; 

    unlink(path); 
    sa.sun_family=AF_UNIX; 
    strncpy(sa.sun_path,(char*) path, sizeof(sa.sun_path)); 

    if((fd_ser=socket(AF_UNIX,SOCK_STREAM,0))<0){ //socket 
     perror((const char*) (size_t) errno); 
     exit(EXIT_FAILURE); 
    } 


    if (bind(fd_ser,(struct sockaddr *)&sa, sizeof(sa))<0){ 
     perror("bind\n"); 
    } 

    listen(fd_ser,10); //listen 


    struct sockaddr_un addr; 
    int addr_size= sizeof(struct sockaddr_un); 

    fd_c=0; 
    while((fd_c=accept(fd_ser,(struct sockaddr*) &addr, (socklen_t*)&addr_size))<0){ 
     printf("waiting for connections...\n"); 
     sleep(2); 
    } 


    //initialize list of people 
    char* Amy="Amy"; 
    char* Mark="Mark"; 

    addPerson(Amy); 
    addPerson(Mark); 

    //now concat the name strings in a buffer to be sent to the client 

    char* people_list; 
    unsigned int list_len; 
    int value; 

    struct person* ptr=(struct person*) malloc(sizeof(struct person)); 
    ptr=p_head; 
    int offset=0; 
    int i=0; 

    while(ptr!=NULL){ 
     i++; 
     people_list=realloc(people_list,i*LENGTH); //every single name has to be LENGTH characters 
     strcpy(&people_list[offset],ptr->name); 
     ptr=ptr->next; 
     offset=offset+LENGTH; 
    } 
    people_list[i*LENGTH]='\0'; 
    list_len=(i*LENGTH)+1; 

    value=write(fd_c, &(list_len), sizeof(unsigned int)); 
    if(value==-1){ 
     perror("write length"); 
     return -1; 
    } 

    int toWrite=list_len; 
    char *toRead=people_list; 
    while(toWrite>0){ 
     value=write(fd_c, toRead, toWrite); 
     if(value==-1){ 
      perror("write data"); 
      return -1; 
     } 
     toWrite=toWrite-value; 
     toRead=toRead+value; 
     if(toRead<=people_list + list_len) break; 
    } 

    close(fd_c); 
    close(fd_ser); 

    return 0; 
} 

客戶端代碼:

#include <stdio.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <string.h> 
#include <pthread.h> 
#include <sys/socket.h> 
#include <sys/un.h> 
#include <assert.h> 
#include <errno.h> 
#define MAX_LENGTH 2048 
#define LENGTH 32 

int main(){ 

    int fd_cli; 
    char* path="tmp/sock"; 
    struct sockaddr_un sa; 
    sa.sun_family=AF_UNIX; 
    strncpy(sa.sun_path,(char*) path, sizeof(sa.sun_path)); 

    if((fd_cli = socket(AF_UNIX, SOCK_STREAM, 0))==-1){ 
     perror((const char*) (size_t) errno); 
     return -1; 
    } 

    while((connect(fd_cli,(struct sockaddr*)&sa, sizeof(struct sockaddr_un))) == -1) { 
     if (errno == ENOENT) { sleep(1); } 
     else perror("connect:"); 
     errno=0; 
     sleep(1); 
    } 

    printf("connected to server\n"); 

    int value; 

    unsigned int len_data; 

    value=read(fd_cli,&(len_data),sizeof(unsigned int)); 
    if(value==-1){ 
     perror("read length"); 
     return -1; 
    } 
    char* buffer=malloc(len_data*sizeof(char)); 

    int toRead=len_data; 
    char *toWrite=buffer; 
    while(toRead>0){ 
     value=read(fd_cli, toWrite, toRead); 
     if(value==-1){ 
      perror("read buffer"); 
      return -1; 
     } 
     toRead=toRead-value; 
     toWrite=toWrite+value; 
     if(toWrite<=buffer + len_data) break; 
    } 


    int people_n = len_data/(LENGTH+1); 
    assert(people_n > 0); //proceeds only if there is at least one person registered 

    printf("Registered people:\n"); 

    for(int i=0,p=0;i<people_n; ++i, p+=(LENGTH+1)) { 
     printf(" %s\n", &buffer[p]); 
    } 

    close(fd_cli); 

    return 0; 

} 

我真的希望我已經清楚地說明了問題!感謝您的幫助!

+0

您可能需要再次仔細閱讀客戶端代碼,特別是'LENGTH'的處理。 – EOF

+1

'struct person * ptr =(struct person *)malloc(sizeof(struct person)); ptr = p_head; '你在這裏泄漏記憶。 – wildplasser

+1

@EOF對!我並沒有考慮客戶端跳過LENGTH + 1個字符,而我沒有考慮在服務器上,現在我修復了它。我多麼失明!謝謝你的提示。 – BattiestFawn66

回答

0

它僅打印,因爲這條線的第一用戶(標記):

int people_n = len_data/(LENGTH+1); 

在這個例子中,len_data = 65LENGTH = 32。所以當你加1到LENGTH時,它會返回1(65/33 = 1.96 => you get 1)。然後它只打印第一個用戶。

考慮使用Valgrind。它將幫助您檢查內存的使用情況。