大学の授業で習っている最中なのですが、通信システムのシミュレーションをしたいプログラムで。出された課題内容がプログラムの機能を拡張するもので。一つ目の課題は特に問題なくクリアしたのですが二つ目でエラーが出てしまいどう解決すればいいかわからず、皆様に直し方をお聞きしたいです。
以前でも同じような課題が出てその課題と類似しています。
strtokでファイル名を","で区切り二つのファイル名を入力後、その二つのファイルの中に入っているものを出力するプログラムを書きたいのですがFile access errorになってしまいます。
strtokの使い方が間違っているのでしょうか?
strtokでjp.txtとch.txtに分けられておらず中身のbufもそれぞれのbut[0]とbuf[1]に格納できていないのでしょうか?
動作環境は大学のパソコンで
仮想マシンCentOS Linux socket通信環境
0. サーバー側
c
1/* コネクション型の簡単なリモートファイル表示サーバ(vc_server.c) */ 2#include <stdio.h> 3#include <stdlib.h> 4#include <sys/types.h> 5#include <sys/socket.h> /* ソケットのための基本的なヘッダファイル */ 6#include <netinet/in.h> /* インタネットドメインのためのヘッダファイル */ 7#include <netdb.h> /* gethostbyname()を用いるためのヘッダファイル */ 8#include <errno.h> 9#include <string.h> 10#define MAXHOSTNAME 64 11#define S_TCP_PORT (u_short)5000 /* 本サーバが用いるポート番号 */ 12#define MAXFILENAME 255 13#define MAXBUFLEN 512 14#define ERR 0 /* ファイルオープン失敗 */ 15#define OK 1 /* 成功 */ 16int setup_vcserver(struct hostent*, u_short); 17void send_file(int); 18 19main() 20{ 21 int socd, socd1; 22 char s_hostname[MAXHOSTNAME]; 23 struct hostent *s_hostent; 24 struct sockaddr_in c_address; 25 int c_addrlen, cpid; 26 27 /* サーバのホスト名とそのIPアドレス(をメンバに持つhostent構造体)を求める */ 28 gethostname(s_hostname, sizeof(s_hostname)); 29 s_hostent = gethostbyname(s_hostname); 30 31 /* バーチャルサーキットサーバの初期設定 */ 32 socd = setup_vcserver(s_hostent, S_TCP_PORT); 33 34 while(1) { 35 /* 接続要求の受け入れ */ 36 c_addrlen = sizeof(c_address); 37 if((socd1 = accept(socd, (struct sockaddr *)&c_address, &c_addrlen)) < 0) { 38 perror("accept"); 39 exit(1); 40 } 41 /* フォーク(並行サーバのサービス) */ 42 if((cpid = fork()) < 0) { perror("fork");exit(1); } 43 else if(cpid == 0) { /* 子プロセス */ 44 close(socd); 45 46 /* クライアントが要求するファイルの送信 */ 47 send_file(socd1); 48 49 close(socd1); 50 exit(0); 51 } 52 else close(socd1); /* 親プロセス */ 53 } 54} 55 56int setup_vcserver(struct hostent *hostent, u_short port) 57{ 58 int socd; 59 struct sockaddr_in s_address; 60 61 /* インターネットドメインのSOCK_STREAM(TCP)型ソケットの構築 */ 62 if((socd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket");exit(1); } 63 64 /* アドレス(IPアドレスとポート番号)の作成 */ 65 bzero((char *)&s_address, sizeof(s_address)); 66 s_address.sin_family = AF_INET; 67 s_address.sin_port = htons(port); 68 bcopy((char *)hostent->h_addr, (char *)&s_address.sin_addr, hostent->h_length); 69 70 /* アドレスのソケットへの割り当て */ 71 if(bind(socd, (struct sockaddr *)&s_address, sizeof(s_address)) < 0) { perror("bind");exit(1); } 72 73 /* 接続要求待ち行列の長さを5とする */ 74 if(listen(socd, 5) < 0) { perror("listen");exit(1); } 75 76 return socd; 77} 78 79void send_file(int socd) /* クライアントが要求するファイルを読み込みソケットに書き出す */ 80{ 81 char filename[MAXFILENAME+1]; 82 FILE *fd; 83 char ack; 84 char buf[i][MAXBUFLEN]; 85 int i=0; 86 char token; 87 char **dbp 88 for(;;) 89 { 90 /* クライアントから送られるファイル名をソケットから読み込む */ 91 recv(socd, filename, MAXFILENAME+1, 0); 92 token = *strtok(filename, ","); 93 do{ 94 while(*dbp){ 95 if(strcmp(&token, *dbp) == 0) { 96 strcpy(buf[i], *(++dbp)); 97 break; 98 } 99 dbp += 1; 100 } 101 i++; 102 }while(token == *strtok(NULL,",")); 103 if(*dbp == NULL) strcpy(*data, "No entry"); 104 /* ファイルを読み出し専用にオープンする */ 105 if((fd = fopen(filename, "r")) != NULL) { /* ファイルオープンに成功した場合 */ 106 /* オープン成功メッセージを送る */ 107 ack = OK; 108 send(socd, &ack, 1, 0); 109 /* ファイルから1行読み込みソケットに書き出すことをEOFを読むまで繰り返す */ 110 printf("ファイル %s を送信\n",filename); 111 while(fgets(buf[i], MAXBUFLEN, fd)) { 112 send(socd, buf[i], strlen(buf[i]), 0); 113 } 114 close(fd); 115 } 116 else 117 { /* ファイルオープンに失敗した場合 */ 118 /* オープン失敗メッセージを送る */ 119 ack = ERR; 120 send(socd, &ack, 1, 0); 121 } 122 } 123} 124
- クライアント側
c
1/* コネクション型の簡単なリモートファイル表示クライアント(vc_client.c) */ 2#include <stdio.h> 3#include <stdlib.h> 4#include <sys/types.h> 5#include <sys/socket.h> /* ソケットのための基本的なヘッダファイル */ 6#include <netinet/in.h> /* インタネットドメインのためのヘッダファイル */ 7#include <netdb.h> /* gethostbyname()を用いるためのヘッダファイル */ 8#include <errno.h> 9#include <string.h> 10#define MAXHOSTNAME 64 11#define S_TCP_PORT (u_short)5000 12#define MAXFILENAME 255 13#define MAXBUFLEN 512 14#define ERR 0 /* ファイルオープン失敗 */ 15#define OK 1 /* 成功 */ 16int setup_vcclient(struct hostent*, u_short); 17void receive_file(int); 18 19main() 20{ 21 int socd; 22 char s_hostname[MAXHOSTNAME]; 23 struct hostent *s_hostent; 24 25 /* サーバのホスト名の入力 */ 26 printf("server host name?: "); scanf("%s",s_hostname); 27 /* サーバホストのIPアドレス(をメンバに持つhostent構造体)を求める */ 28 if((s_hostent = gethostbyname(s_hostname)) == NULL) { 29 fprintf(stderr, "server host does not exists\n"); 30 exit(1); 31 } 32 33 /* バーチャルサーキットクライアントの初期設定 */ 34 socd = setup_vcclient(s_hostent, S_TCP_PORT); 35 36 /* サーバにファイルを要求し受信したファイルの内容を標準出力に出力 */ 37 receive_file(socd); 38 39 close(socd); 40 exit(0); 41} 42 43int setup_vcclient(struct hostent *hostent, u_short port) 44{ 45 int socd; 46 struct sockaddr_in s_address; 47 48 /* インターネットドメインのSOCK_STREAM(TCP)型ソケットの構築 */ 49 if((socd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket");exit(1); } 50 51 /* サーバのアドレス(IPアドレスとポート番号)の作成 */ 52 bzero((char *)&s_address, sizeof(s_address)); 53 s_address.sin_family = AF_INET; 54 s_address.sin_port = htons(port); 55 bcopy((char *)hostent->h_addr, (char *)&s_address.sin_addr, hostent->h_length); 56 57 /* サーバとの接続の確立 */ 58 if(connect(socd, (struct sockaddr *)&s_address, sizeof(s_address)) < 0) { perror("connect");exit(1); } 59 60 return socd; 61} 62 63void receive_file(int socd) /* サーバから受け取ったファイルの内容を表示する */ 64{ 65 char filename[MAXFILENAME+1]; 66 int filename_len; 67 char ack; 68 char buf[i][MAXBUFLEN]; 69 int length; 70 int i; 71 72 for(;;) 73 { 74 /* ファイル名の入力 */ 75 printf("remote file name?: "); 76 if(scanf("%s",filename)==EOF)break; 77 /* ファイル名をソケットに書き込む */ 78 filename_len = strlen(filename); 79 send(socd, filename, filename_len+1, 0); 80 /* ファイルオープンに成功したかどうかのメッセージをソケットから読み込む */ 81 recv(socd, &ack, 1, 0); 82 switch (ack) { 83 case OK: /* ファイルオープンに成功した場合 */ 84 printf("ファイル %s を受信\n", filename); 85 /* ソケットから読み込み標準出力に書き出す */ 86 while(length = recv(socd, buf[i], MAXBUFLEN, 0)) { 87 buf[i][length] = '\0'; 88 for(i=0;i<5;i++){ 89 90 fputs(buf[i], stdout); 91 } 92 break; 93 } 94 printf("\n"); 95 break; 96 case ERR: /* ファイルオープンに失敗した場合 */ 97 fprintf(stderr, "File access error\n"); 98 break; 99 } 100 } 101} 102
実行結果:
[root@skt35 Linux_share]# gcc -o client client.c
[root@skt35 Linux_share]# ./client
server host name?: skt35
remote file name?: jp.txt,ch.txt
File access error
[root@skt35 Linux_share]# gcc -o server server.c
[root@skt35 Linux_share]# ./server
//何も表示されない
サーバー側(第一課題を実行できていたもの)
c
1void send_file(int socd) /* クライアントが要求するファイルを読み込みソケットに書き出す */ 2{ 3 char filename[MAXFILENAME+1]; 4 FILE *fd; 5 char ack; 6 char buf[MAXBUFLEN]; 7 for(;;) 8 { 9 /* クライアントから送られるファイル名をソケットから読み込む */ 10 recv(socd, filename, MAXFILENAME+1, 0); 11 /* ファイルを読み出し専用にオープンする */ 12 if((fd = fopen(filename, "r")) != NULL) { /* ファイルオープンに成功した場合 */ 13 /* オープン成功メッセージを送る */ 14 ack = OK; 15 send(socd, &ack, 1, 0); 16 /* ファイルから1行読み込みソケットに書き出すことをEOFを読むまで繰り返す */ 17 printf("ファイル %s を送信\n",filename); 18 while(fgets(buf, MAXBUFLEN, fd)) { 19 send(socd, buf, strlen(buf), 0); 20 } 21 close(fd); 22 printf("\n"); 23 } 24 else 25 { /* ファイルオープンに失敗した場合 */ 26 /* オープン失敗メッセージを送る */ 27 ack = ERR; 28 send(socd, &ack, 1, 0); 29 } 30 } 31}
クライアント側(第一課題を実行できたもの)
c
1void receive_file(int socd) /* サーバから受け取ったファイルの内容を表示する */ 2{ 3 char filename[MAXFILENAME+1]; 4 int filename_len; 5 char ack; 6 char buf[MAXBUFLEN]; 7 int length; 8 for(;;) 9 { 10 11 /* ファイル名の入力 */ 12 printf("remote file name?: "); 13 printf("what"); 14 if(scanf("%s",filename)==EOF)break; 15 printf("at"); 16 /* ファイル名をソケットに書き込む */ 17 filename_len = strlen(filename); 18 printf("that"); 19 send(socd, filename, filename_len+1, 0); 20 printf("chat"); 21 /* ファイルオープンに成功したかどうかのメッセージをソケットから読み込む */ 22 recv(socd, &ack, 1, 0); 23 printf("hat"); 24 switch (ack) { 25 case OK: /* ファイルオープンに成功した場合 */ 26 printf("ファイル %s を受信\n", filename); 27 /* ソケットから読み込み標準出力に書き出す */ 28 while(length = recv(socd, buf, MAXBUFLEN, 0)) { 29 buf[length] = '\0'; 30 fputs(buf, stdout); 31 break; 32 } 33 break; 34 case ERR: /* ファイルオープンに失敗した場合 */ 35 fprintf(stderr, "File access error\n"); 36 break; 37 } 38 } 39}
サーバー側とクライアント側ともに最後の関数しか変更しておらず、この部分のみの状態でしたら実行できました。
今回に関しては複数の入力に対して複数の出力ができればいいので。特に","で区切らないといけないという訳でもなく、複数という条件しか出されていなかったので最小二つに対応できればいいです。
回答1件
あなたの回答
tips
プレビュー