通过套接字发送/接收数据时出现问题

时间:2019-10-09 10:52:55

标签: c linux sockets ncurses

我正在使用C中的ncurses UI开发一个简单的聊天程序,并且遇到了这个奇怪的问题。

过程如下:

  1. 服务器等待客户端连接。

  2. 连接客户端后,服务器会提示输入用户名。

  3. 在接收到用户名之后,服务器开始侦听来自客户端的消息。

  4. 每个时间服务器收到一条消息,它将其与用户名连接起来,并将其广播给所有客户端,因此客户端收到的消息应如下所示:

username: text 

这是出问题的地方。

客户端输出:

test^U^D: hello waddup

因此,基本上,如果用户名少于6个字母,则接收到的数组的前六个索引总是填充有这些转义字符,这些转义字符打印在客户端上。

像这样:

USERNAME: a //user input                             
YOU: test message                                    a^C^\^?^U^D: test message

在调查此问题时,我已在服务器端添加了调试消息。

服务器输出:

USERNAME RECEIVED:
: message
//tested one-letter username - q
USERNAME RECEIVED: q
q: asd
//two-letter - qw
USERNAME RECEIVED: as
as: sdf
//three-letter - asd. Still doesn't print the last letter, eventhough on client side it is printed, probably some stupid mistake I've made and didn't notice yet
USERNAME RECEIVED: test
test: hello
//Finally prints full u-name. No escape characters like on client side.
//If u-name >= 4 let. it is displayed normally on server side. If uname >= 6 -- on client side

我的猜测是该问题出现在套接字层上,但我不是 套接字编程方面的知识渊博,对我的建议充满信心。

或者,该问题可能与ncurses用户界面有关,因为它在客户端(使用ncurses)可见,而在服务器端(将调试消息打印到sdout)不可见。

我知道它可能确实很杂乱且效率低下,但是这个项目是我的第一个相对认真的C项目,我肯定以后会重构和优化此代码。

服务器端有问题的功能代码:

void transmitt(int socket, int index){
        printf("CONNECTION TO THREAD %x\n", pthread_self());
        char tmp[MAX];
        char bye[MAX];
        char uname[MAX_UNAME];
        char buffer[MAX+MAX_UNAME];
        sprintf(bye, "%d", BYE_MESSAGE);
        recv_uname(socket, uname);
        while(1){
                bzero(tmp, sizeof(tmp));
                bzero(buffer, sizeof(buffer));
                recv(socket, tmp, sizeof(tmp), 0);
                if(strncmp(bye, tmp, MAX) == 0){
                        printf("THREAD: %x DISCONNECTED\n", pthread_self());
                        snprintf(buffer, sizeof(buffer), "SERVER MESSAGE: %s HAS DISCONNECTED", uname);
                        for(int i =0;i<MAX_CLIENTS;i++){
                                if(clients[i] != NULL){
                                        send(clients[i], buffer, sizeof(buffer), 0);
                                }
                        }
                        clients[index] = NULL;
                        return;
                }
                snprintf(buffer, sizeof(buffer), "%s: %s", uname, tmp);
                for(int i =0;i<MAX_CLIENTS;i++){
                        if(clients[i] != NULL){
                                send(clients[i], buffer, sizeof(buffer), 0);
                        }
                }
                printf("%s\n", buffer);
        }
}

void recv_uname(int socket, char* uname){
        char prompt[MAX_UNAME];
        snprintf(prompt, sizeof(prompt), "USERNAME: ");
        send(socket, prompt, sizeof(prompt), 0);
        recv(socket, uname, MAX_UNAME, 0);
        printf("USERNAME RECEIVED: %s\n", uname);
}

客户端:

void chat_loop(int socket){
        char buff[MAX], sbuff[MAX+MAX_UNAME];
        char tmp;
        int n, y=0, x=0, maxcol, maxrow, recy, recx;
        getmaxyx(stdscr, maxrow, maxcol);
        recy = 0;
        recx = maxcol/2;
        timeout(1);
        bzero(buff, sizeof(buff));
        printw("YOU: ");
        n=0;
        while(1){
                tmp = getch();
                getyx(stdscr, y, x);
                if(tmp == '`'){
                        sprintf(buff, "%d", BYE_MESSAGE);
                        send(socket, buff, sizeof(buff), 0);
                        return;
                }
                else if(tmp == '\n'){
                        send(socket, buff, sizeof(buff), 0);
                        bzero(buff, sizeof(buff));
        //              printw("YOU: ");
                        move(++y, 0);
                        n=0;
                }
                else if(tmp == ALT_BACKSPACE){
                        if(x > 0){
                                mvdelch(y, x-1);
                                buff[--n] = NULL;
                        }
                }
                else if(tmp != ERR){
                        printw("%c", tmp);
                        buff[n++] = tmp;
                }

                bzero(sbuff, sizeof(sbuff));
                recv(socket, sbuff, sizeof(sbuff), MSG_DONTWAIT);
                if(check_buff(sbuff, sizeof(sbuff)) == 0){
                        getyx(stdscr, y, x);
                        move(recy++, recx);
                        printw("%s", sbuff);
                        move(y, x);
                }
                refresh();
        }
}

void send_uname(int socket){
        char buff[MAX], unbuff[MAX_UNAME];
        char tmp;
        int n=0, y=0, x=0, init_x;
        bzero(buff, sizeof(buff));
        recv(socket, buff, sizeof(buff), 0);
        printw("%s", buff);
        getyx(stdscr, y, init_x);
        while((tmp = getch())!='\n'){
                getyx(stdscr, y, x);
                if(tmp == ALT_BACKSPACE){
                        if(x > init_x){
                                mvdelch(y, x-1);
                                unbuff[--n] = NULL;
                        }
                }
                else if(tmp != ERR){
                        if(n < MAX_UNAME){
                                printw("%c", tmp);
                                unbuff[n++] = tmp;
                        }
                }
                refresh();
        }
        printw("\n");
        send(socket, unbuff, sizeof(unbuff), 0);
}

int check_buff(char* buffer, size_t n){
        for(int i=0;i<n;i++){
                if(buffer[i]!=NULL)
                        return 0;
        }
        return -1;
}

常量,包括:

#include<stdio.h>
#include<stdlib.h>
#include <netdb.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>
#include<ncurses.h>

//common
#define ALT_BACKSPACE 127
#define MAX 128 //common buffer size
#define MAX_UNAME 24
#define BYE_MESSAGE 10101010

//server-specific
#define MAX_THREADS 4
#define MAX_CLIENTS 4

GitHub link with full code

这就是我所拥有的。

0 个答案:

没有答案
相关问题