TCP型クライアントで入力した文字列をサーバで計算してクライアントに返すというプログラミングが分かりません。サーバ側だけ変更すればいいのでどこをどうしたらいいか教えていただきたいです。strtok関数等を使うというところまではわかるのですが・・・
c
1#include <winsock.h> 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5#include <ctype.h> 6 7#pragma comment(lib,"wsock32.lib") 8 9#define MAX_BUFF_12A 1024 10 11int ServerPort = 10010; 12 13 14int main( void ) 15{ 16 char StrBuf[128] ; 17 int rVal; 18 SOCKADDR_IN local, from; 19 WSADATA wsaData ; 20 SOCKET listen_socket; //Listen用ソケット 21 SOCKET DataSocket; //送受信用ソケット 22 WORD wVersionRequested ; 23 int fromlen = sizeof( from ) ; 24 25 26 27 printf("サーバ起動時のポート番号(1024以上):"); scanf("%d", &ServerPort); 28 29 30 31 32 wVersionRequested = MAKEWORD( 1, 1 ); 33 rVal = WSAStartup( wVersionRequested, &wsaData ); 34 if(rVal != 0 ) { 35 printf("エラー:ソケット初期化・・・終了します\n"); 36 WSACleanup(); 37 return(-1); 38 } 39 40 local.sin_family = AF_INET ; 41 local.sin_addr.s_addr = INADDR_ANY ; 42 local.sin_port = htons( (unsigned short)ServerPort ); 43 44 45 listen_socket = socket( AF_INET, SOCK_STREAM, 0 ) ; 46 if( listen_socket == INVALID_SOCKET ) { 47 printf("エラー:ソケット生成・・・終了します\n"); 48 WSACleanup(); 49 return(-1); 50 } 51 52 53 if( bind( listen_socket, (struct sockaddr*)&local, sizeof(local) ) 54 == SOCKET_ERROR) { 55 printf("エラー:バインドbind・・・終了します\n"); 56 WSACleanup(); 57 return(-1); 58 } 59 printf("******サーバの起動*****\n"); 60 61 listen( listen_socket, 5 ); 62 printf("ポート番号%dをlistning中(接続待ち)...", ServerPort ); 63 64 DataSocket = accept( listen_socket, (struct sockaddr*)&from, &fromlen ); 65 printf("\nサーバ=%s, ポート番号=%dに接続.\n\n", 66 inet_ntoa(from.sin_addr), htons(from.sin_port) ) ; 67 68 69 70 71 /******** データの受信 ********/ 72 while (1) { 73 rVal = recv(DataSocket, StrBuf, sizeof(StrBuf), 0); 74 StrBuf[rVal] = '\0'; 75 76 if (rVal == SOCKET_ERROR || rVal == 0) { 77 printf("エラー:相手からの切断されました\n・・・終了します\n"); 78 break; 79 } 80 if (StrBuf == '.') 81 break; 82 83 /******** 受信したデータ(文字列)をホスト画面に表示 *********/ 84 printf("%s\n", StrBuf); 85 86 /******** 文字列の送信 *********/ 87 send(DataSocket, StrBuf, (int)strlen(StrBuf), 0); 88 89 } 90 91 92 // ソケット終了処理 93 closesocket( DataSocket ); 94 WSACleanup(); 95 96 printf("\n\nEnterキーを1,2回押してプログラム終了"); 97 getchar(); 98 getchar(); 99 100 return(0); 101} 102
#include <winsock.h> //Windows用ソケットライブラリ用 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #pragma comment(lib,"wsock32.lib") //WinSockライブラリをリンク #define MAX_BUFF_12A 1024 // バッファの長さ int NetPortNo = 10010; char HostAddr[50] = "127.0.0.1"; // // main // int main( void ) { char StrBuf[MAX_BUFF_12A+1] ; char szHost[MAX_BUFF_12A+1]; SOCKET DataSocket; WSADATA wsaData; SOCKADDR_IN server; HOSTENT *hostEnt; int rVal; WORD wVersionRequested; unsigned int addr; // ソケットの初期化(ウィンドウズ用Winsockの初期化) wVersionRequested = MAKEWORD( 1, 1 ); rVal = WSAStartup( wVersionRequested, &wsaData ); //初期化の関数 if(rVal != 0 ) { //初期化のエラー printf("エラー:ソケット初期化・・・終了します\n"); WSACleanup(); return(-1); } // ソケット生成(TCPソケット) DataSocket = socket( AF_INET, SOCK_STREAM, 0 ) ; // ソケット生成の関数 if( DataSocket < 0 ) { printf("エラー:ソケット生成・・・終了します\n"); return(-1);} printf("サーバのホスト名(またはIPアドレス):"); scanf("%s",HostAddr); printf("サーバのポート番号:"); scanf("%d",&NetPortNo); strcpy( szHost, HostAddr ); if( isalpha( szHost[0] ) ) { hostEnt = gethostbyname( szHost ); } else { addr = inet_addr( szHost ); hostEnt = gethostbyaddr( (char*)&addr, 4, AF_INET ); } if( hostEnt == NULL ) { printf("エラー:アドレスを解決不能[%s]\n・・終了!\n", szHost);return(-1); } printf("******クライアントの起動*****\n"); // サーバ接続のための初期化 memset( &server, 0, sizeof(server) ); memcpy( &(server.sin_addr), hostEnt->h_addr, hostEnt->h_length ); server.sin_family = hostEnt->h_addrtype; server.sin_addr.s_addr = *(( unsigned long*)hostEnt->h_addr ); //サーバアドレス server.sin_port = htons( (unsigned short)NetPortNo ); // サーバのポート番号の設定 <---------- ポート! // サーバへ接続を試みる(connect関数) printf("サーバ[%s]へ接続中...", szHost ) ; if( connect( DataSocket,(struct sockaddr*)&server, sizeof(server) ) == SOCKET_ERROR) { printf("エラー:サーバへの接続(connect)\n・・・終了します\n"); return(-1); } printf("%sに接続完了しました\n", szHost ); /******** 文字列のキーボードからの読込み *********/ while (1) { printf("文字列を入力:"); scanf("%s", StrBuf); getchar(); /******** 文字列の送信 *********/ send(DataSocket, StrBuf, (int)strlen(StrBuf), 0); //送信(send関数) if (StrBuf[0] == '.') break; /******** データの受信 ********/ rVal = recv(DataSocket, StrBuf, sizeof(StrBuf), 0); //受信(recv関数) StrBuf[rVal] = '\0'; //受信したデータ(文字列)の最後にNULL文字付加 if (rVal == SOCKET_ERROR || rVal == 0) { //受信時エラー(または切断) printf("エラー:相手からの切断されました\n・・・終了します\n"); break; } printf("受信文字列:%s\n", StrBuf); } // ソケット終了処理 closesocket( DataSocket ); //ソケットのクローズ WSACleanup(); //ソケットの破棄 printf("\n\nEnterキーを1,2回押してプログラム終了"); getchar(); getchar(); return(0); }
> 文字列をサーバで計算して
どんな文字列を計算してどう返すのでしょう. 具体例がありましたら追記をお願い致します.
返信ありがとうございます。大事な所が抜けていました申し訳ないです。
具体的には「add,30,10」,「sub,40,10」など「,」で3つに区切られた四則演算ができるものです。
「add,30,10」が来たら「40」, 「sub,40,10」が来たら「30」を返すことになるのでしょうか.
四則演算ということは 乗除もあるわけですが, その場合の最初のキーワードは "mul" と "div" でしょうか.
計算できない文字列だった場合(キーワードが加減乗除では無かったり, 数値が文字だったり, 0割だったり等々)は考慮が必要ですか? 考慮する場合, 何を返せば良いのでしょうか.
計算は
> /******** 受信したデータ(文字列)をホスト画面に表示 *********/
> printf("%s\n", StrBuf);
と
> /******** 文字列の送信 *********/
> send(DataSocket, StrBuf, (int)strlen(StrBuf), 0);
の間で, StrBuf の式を計算して StrBuf に入れ直す(もしくは別に文字列を作る)形となるのでしょうか.
出力例を確認しました。クライアント側に返された時には「add,30,10」が入力された場合には、「30+10=40」と返すようになっています。乗除の場合は仰る通りのキーワードです。
計算できない文字列だった場合「”入力された文字列”の計算はできません」と表示したいです。(入力された文字列にはそのまま「abc,30,10」など間違った文字列を入れたい)
計算方法はおそらくjimbe様の提案された形になるかと思います
数値部分に関しましては何か指示はありましたでしょうか. 整数のみであったり, 少数, 負数, 桁数等ですが.
整数のみ計算できれば良いようでした。桁数の指定はありませんでした
TCP通信の部分はできるはずなのでそこはもう問題ではなくて、計算が正しくできるようになれば本質問の目的は達成できる、と言うことしょうか。
はい。送受信はできるのでサーバ側で計算をしてそれをクライアント側に返したいのです
strtokの使い方のどこが分からないのか、具体的に書いてください。
回答1件
あなたの回答
tips
プレビュー