2016-07-11 4 views
1

UNIXトーククローンで正しく印刷するために、UTF-8とスウェーデン文字ÅÄÖを取得しようとすると、私は困っています。首都ÅÄÖ正しく印刷されない

setLocale()でロケールをsv_SEに設定しました。文字を正しく表示しようとするためにワイド文字を使用していますが、小文字のåäöはうまく動作しますが、大文字と小文字の違いは機能しません。

以下はコード全体です。reader()、sender()、putch()の文字サイズが不足していると思われます。

#define _GNU_SOURCE 
#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <ncurses.h> 
#include <pthread.h> 
#include <signal.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <sched.h> 
#include <pthread.h> 
#include <locale.h> 
#include <wchar.h> 
#define MATRIXSIZE 1000 
#define STACKSIZE 10000 
#define CHATLEN 2048 

#include <syslog.h> 

int r = 0, i = 0, mode = -1; 
wchar_t mybuf[CHATLEN], tmbuf[CHATLEN]; 

WINDOW *me; 
WINDOW *them; 

struct stuff { 
    unsigned int col, row, size, realsize; 
    pid_t childpid; 
    pid_t mainpid; 
    char matrix[MATRIXSIZE]; 
    char nukeline[1024]; 
    int nukesize; 
    int terminate; 
    struct massaskit { 
     int writechan; 
     int readchan; 
     int sockfd; 
     struct sockaddr_in server; 
     struct sockaddr_in writeclient; 
     struct sockaddr_in readclient; 
     int c; 
     struct hostent *serverhost; 
     char hostname[256]; 
     uint16_t port; 
    } bertil; 
}; 

pthread_mutex_t scr_mutex = PTHREAD_MUTEX_INITIALIZER; 
pthread_t sendthread; // Thread that listens to user's typing, and 
         // puts the characters on the screen, and 
         // transmits them over the network. 

pthread_t readthread; // Thread that reads characters from the network 
         // and shows them on the screen. 

int srv1(void *ptr) 
{ 
    struct massaskit *sockstuff = (struct massaskit *)ptr; 
    int opt = 1; 

    if ((sockstuff->sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
     perror("socket();"); 
     exit(-1); 
    } 

    sockstuff->server.sin_family = AF_INET; 
    sockstuff->server.sin_addr.s_addr = INADDR_ANY; 
    sockstuff->server.sin_port = htons(sockstuff->port); 
    setsockopt(sockstuff->sockfd, SOCK_STREAM, SO_REUSEADDR, &opt, 
      sizeof(opt)); 

    if (bind 
     (sockstuff->sockfd, (struct sockaddr *)&sockstuff->server, 
     sizeof(sockstuff->server)) < 0) { 
     perror("bind failed"); 
     exit(-1); 
    } 

    if ((listen(sockstuff->sockfd, 3)) < 0) 
    { 
     perror("listen"); 
     exit(-1); 
    } 

    sockstuff->c = sizeof(struct sockaddr_in); 
    printf("waiting for readchan on %i sockstuff->port..\n", 
      sockstuff->port); 
    sockstuff->readchan = 
     accept(sockstuff->sockfd, 
      (struct sockaddr *)&sockstuff->readclient, 
      (socklen_t *) & sockstuff->c); 

    printf("got a connection! now need a connection on writechan (p:%i)\n", 
      sockstuff->port); 

    sockstuff->writechan = 
     accept(sockstuff->sockfd, 
      (struct sockaddr *)&sockstuff->writeclient, 
      (socklen_t *) & sockstuff->c); 

    printf("got a connection! both read/write (p:%i)\n", sockstuff->port); 
    shutdown(sockstuff->writechan, SHUT_RD); 
    shutdown(sockstuff->readchan, SHUT_WR); 

    if (close(sockstuff->sockfd) != 0) 
    { 
     exit(1); 
    } 

    return 0; 
} 

int cli1(void *ptr) 
{ 
    /* srv1 starts with readchan, we start with writechan :-) */ 
    struct massaskit *sockstuff = (struct massaskit *)ptr; 
    int opt = 1; 
    sockstuff->sockfd = -1; /* make it broken so other function understand */ 
    if ((sockstuff->writechan = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
     perror("writechan->socket()"); 
     exit(-1); 
    } 
    else 
    { 
     printf("socket init is ok.got fd[%i] [writechan]\n", 
       sockstuff->writechan); 
    } 

    setsockopt(sockstuff->writechan, SOCK_STREAM, SO_REUSEADDR, &opt, 
      sizeof(opt)); 

    if ((sockstuff->serverhost = 
     gethostbyname(sockstuff->hostname)) == NULL) { 
     perror("error in resolving hostname :/\n"); 
     exit(-1); 
    } 
    else 
    { 
     printf("ok, resolved host, now making connection [writechan]!\n"); 
    } 

    memset(&sockstuff->server, '\0', sizeof(struct in_addr)); 
    sockstuff->server.sin_family = AF_INET; 
    memcpy(&sockstuff->server.sin_addr.s_addr, 
      sockstuff->serverhost->h_addr, 
      (size_t) sockstuff->serverhost->h_length); 
    sockstuff->server.sin_port = htons(sockstuff->port); 

    if (connect 
     (sockstuff->writechan, (struct sockaddr *)&sockstuff->server, 
     sizeof(sockstuff->server)) == -1) { 
     perror("connection"); 
     exit(-1); 
    } 
    else 
    { 
     printf("%s%s", "writechan established,starting readchan and", "sleeping 2s so other end can initalize the readchan.\n"); 
    } 
    if ((sockstuff->readchan = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
     perror("socket();"); 
     exit(-1); 
    } 
    else 
    { 
     printf("readchan socket init ok.\n"); 
     fflush(stdout); 
    } 

    setsockopt(sockstuff->readchan, SOCK_STREAM, SO_REUSEADDR, &opt, 
      sizeof(opt)); 

    if ((sockstuff->serverhost = gethostbyname(sockstuff->hostname)) == NULL) 
    { 
     perror("error in recieve channel, could'nt resolve host bailing.\n"); 
     exit(-1); 
    } 
    else 
    { 
     printf("readchan could resolve host nice shit alabama\n"); 
     fflush(stdout); 
    } 

    memset(&sockstuff->server, '\0', sizeof(struct in_addr)); 
    sockstuff->server.sin_family = AF_INET; 
    memcpy(&sockstuff->server.sin_addr.s_addr, 
      sockstuff->serverhost->h_addr, 
      (size_t) sockstuff->serverhost->h_length); 

    sockstuff->server.sin_port = htons(sockstuff->port); 
    if (connect 
     (sockstuff->readchan, (struct sockaddr *)&sockstuff->server, 
     sizeof(sockstuff->server)) == -1) { 
     perror("connect()"); 
     exit(-1); 
    } 
    else 
    { 
     printf("read chan estabiled. starting program!\n"); 
     fflush(stdout); 
    } 

    return 0; 
} 

void putch(WINDOW * win, wchar_t ch) 
{ 
    syslog(LOG_INFO, "%04x", ch); 
    if (ch == 4 || ch == 7) // Translate left-arrow, backspace to CTL-H 
     ch = '\b'; 
    if(ch < ' ' && ch != '\t' && 
     ch != '\n' && ch != '\b' 
    ) 
    { 
     return; 
    } 

    pthread_mutex_lock(&scr_mutex); // Get exclusive access to screen. 
    wechochar(win, ch); 

    if (ch == '\b') 
    { 
     wdelch(win); 
     refresh(); 
    } 

    pthread_mutex_unlock(&scr_mutex); 
} 

void setupscreen() 
{ 
    int rows, cols; 
    initscr(); 
    cbreak(); 
    noecho(); 
    intrflush(stdscr, FALSE); 
    rows = (LINES - 3)/2; 
    cols = COLS - 2; 
    me = newwin(rows, cols, 1, 1); 
    them = newwin(rows, cols, rows + 2, 1); 
    idlok(me, TRUE); 
    scrollok(me, TRUE); 
    keypad(me, TRUE); 
    idlok(them, TRUE); 
    scrollok(them, TRUE); 
    border(0, 0, 0, 0, 0, 0, 0, 0); 
    move(rows + 1, 1); 
    hline(0, cols); 
    refresh(); 
} 

void* sender(void *ptr) { 
    struct stuff *s = (struct stuff *)ptr; 
    setupscreen(); 

    int ch; 
    while (1) 
    { 
     if (i > CHATLEN - 1) 
     { 
      i = 0; 
     } 

     ch = wgetch(me); 
     mybuf[i] = ch; 
     if (ch == KEY_RESIZE) 
     { 
      clear(); 
      endwin(); 
      setupscreen(); 
      wchar_t *p = &mybuf[0]; 
      while (&(*p) < &mybuf[CHATLEN - 1]) 
      { 
       putch(me, (*p)); 
       p++; 
      } 

      p = &tmbuf[0]; 
      while (&(*p) < &tmbuf[CHATLEN - 1]) 
      { 
       putch(them, (*p)); 
       p++; 
      } 

      refresh(); 
     } 
     else 
     { 
      putch(me, mybuf[i]); 
      int writefd = s->bertil.writechan; 
      write(writefd, &mybuf[i], sizeof(mybuf[i])); 
     } 
      i++; 
    } 
    pthread_cancel(sendthread); 
    return NULL; 
} 

void* reader(void *ptr) { 
    struct stuff *s = (struct stuff *)ptr; 
    int ch; 

    while(1) 
    { 
     if(r> CHATLEN - 1) 
     { 
      r = 0; 
     } 

     int readfd=s->bertil.readchan; 
     if((read(readfd,&ch,sizeof(ch))) == 0) 
     { 
      endwin(); 
      refresh(); 
      return 0; 
     } 

     tmbuf[r] = ch; 
     putch(them, tmbuf[r]); 
     r++; 
    } 
     pthread_cancel(readthread); 
     return NULL; 
} 

int main(int argc, char *argv[]) 
{ 
    setlocale(LC_ALL, "sv_SE"); 
    memset(mybuf, 0, CHATLEN); 
    memset(tmbuf, 0, CHATLEN); 

    struct stuff s; 
    memset(&s, 0, sizeof(struct stuff)); 

    if (argc == 1) 
    { 
     printf("usage %s port  [host server on port]\n", argv[0]); 
     printf("usage %s port host [connecto host:port]\n", argv[0]); 
     exit(1); 
    } 
    else if (argc == 3) 
    { 
     s.bertil.port = (uint16_t) atoi(argv[1]); 
     memset(s.bertil.hostname, 0, 256); 
     memcpy(s.bertil.hostname, argv[2], strlen(argv[2])); 
     cli1(&s.bertil); 
    } 
    else if (argc == 2) 
    { 
     s.bertil.port = (uint16_t) atoi(argv[1]); 
     srv1(&s.bertil); 
    } 

    pthread_create(&readthread, NULL, reader, &s); 
    pthread_create(&sendthread, NULL, sender, &s); 
    pthread_join(sendthread, NULL); 
    pthread_join(readthread,NULL); 
} 

あなたは試してみたい場合は、次のようにプログラムがそれをコンパイルします。

のgcc file.cと-lpthread -lncurses

奉仕する:

。 /a.out 1234

は、接続するには:任意の助けをいただければ幸いです

localhostの1234 ./a.out!

+0

? – rici

+0

あなたのプログラムは私の環境で非常にうまく動作します。環境変数 'LC_TYPE'と' LC_ALL'を指定できますか? –

+0

'setlocale(LC_ALL、" sv_SE ");'を呼び出すべきではありません。代わりに 'setlocale(LC_ALL、" ");'を呼び出して環境からロケールを取得する必要があります。 – caf

答えて

2

実際には、wchar_tで十分です。符号拡張の問題が発生する可能性は低いです。

しかし、2つのスレッド(senderreader)でncursesを使用するアプリケーションで、特別にコンパイルしてmutexを許可しない限り、正常に動作しません。 ncurses(cursesの実装と同様)は、画面を維持するためのグローバル変数を使用します。複数のスレッドが予期しない方法でライブラリを実行します。

さらに読書:

  • Official releases(ncursesベースのFAQ):

    5.7(2008年11月2日)。これにより、スレッド化されたアプリケーションに対する基本的なサポートが提供されます。また、別々にタックを分配します。

  • curs_threads - curses thread support `ÅÄÖ`とどうなります(ncursesのマニュアルページ)
1

intの代わりにunsigned charをお試しください。

putchでは、wchar_tunsigned char(1バイト)はUTF-8(http://www.science.co.il/language/Character-code.asp?s=1252)で問題ありません。

+0

ワイド文字を削除し、リーダと送信者の整数を符号なしの文字に置き換えましたが、大文字のÅÄÖは動作しませんが、今では小文字のåäöを使用しています。 – JazzCat

+0

あなたのバッファと関連する関数のwchar_tも置き換えましたか? –

+0

はい私はそれをしました – JazzCat

関連する問題