質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

Q&A

解決済

1回答

1420閲覧

【6月29日までにお願い致します】TCPサーバ・クライアントでのデータ送受信を行う際のデータ格納に関する質問

nana_7310

総合スコア1

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

11グッド

0クリップ

投稿2022/06/20 18:40

編集2022/06/21 01:54

至急(6月29日まで)お願い致します。

大学の課題でTCPクライアントとサーバで通信を行い、座標データを送受信してオセロを行うというものをやっています。

<自分で埋めなければならない場所>
課題①→自身の座標情報(onArea.x , onArea.y)の値を送信文字列(StrBuf)に格納する処理
課題②→受信文字列(StrBuf)の値を自身の座標情報(onArea.x , onArea.y)に格納する処理

<プログラムの仕様>

  1. クライアントが先攻、サーバが後攻でゲームが進む。
  2. サーバ・クライアント間では、相手がそれぞれ「盤面のどこに石を置いたか」を互いに通信により送受信する。
  3. 受信した情報をもとにそれぞれが、turn_stone()関数を用いて盤面の石を返すものとする。
  4. 「盤面のどこに石を置いたか」の情報は、onArea オブジェクトに格納される。
  5. onArea オブジェクトのメンバーには、onArea.y(縦の位置)、 onArea.x(横の位置)が格納される(onArea.y

とonArea.x 値の範囲は0 から7 まで)。
6. クライアント・サーバ間のデータ送受信ではStrBuf を使用する。

上記の処理を行うプログラミングを書くのですが、クライアント側ではオセロはできるもののうまく送信できず(もしくは受信)サーバ側でオセロができません。文字列に値を格納する際、0にならないよう1を加算して格納することと、int型からchar型への格納なのでキャストを行うことはわかっています。

また、実際に課題①には
StrBuf[1] = (char)(onArea.x+1);
StrBuf[2] = (char)(onArea.y + 1);
と書きました。これは一応動作しています。

課題②には
onArea.x=(int)(StrBuf[1]-1);
onArea.y=(int)(StrBuf[2]-1);

onArea.x=StrBuf[1]-1;
onArea.y=StrBuf[2]-2;
など書いてみたのですがうまく動きません。
何が間違っているのかもわからないため、アドバイスをいただきく質問致しました。

TCPクライアントのプログラムを添付致しますので、どなたかお力を貸していただけないでしょうか。
ちなみに、サーバ側も課題①と課題②を書くスペースがありますが、クライアント側で書いたものとおなじものが入ります。

<TCPクライアントプログラム>
#include <winsock.h> //Windows用ソケットライブラリ用
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Othello.h"
#pragma comment(lib,"wsock32.lib") //WinSockライブラリをリンク
#pragma warning( disable: 4996 ) // scanfとmemcpy実行の際のwarningを非表示にする
#define MAX_BUFF_12A 1024 // バッファの長さ
int PortNum = 10010; //ポート番号
char hostname[50] = "127.0.0.1"; //サーバのアドレス
// メイン関数
int main( void )
{
char StrBuf[MAX_BUFF_12A + 1] ;
char szHost[MAX_BUFF_12A + 1];
SOCKET data_socket;
WSADATA wsaData;
SOCKADDR_IN server;
HOSTENT *hostEnt;
int rVal;
WORD wVersionRequested;
unsigned int addr;
coordinate onArea;
//ソケットの初期化(ウィンドウズ用WinSockの初期化)
wVersionRequested = MAKEWORD( 1, 1 );
rVal = WSAStartup( wVersionRequested, &wsaData ); //初期化の関数
if(rVal != 0 || wsaData.wVersion != wVersionRequested) { //初期化のエラー
printf("エラー:ソケット初期化・・・終了します\n");
WSACleanup();
return(-1);
}
//ソケット生成(TCPソケット)
data_socket = socket( AF_INET, SOCK_STREAM, 0 ) ; // ソケット生成の関数
if( data_socket < 0 ) {
printf("エラー:ソケット生成・・・終了します\n");
WSACleanup();
return(-1);
}

// サーバ情報の取得 strcpy( szHost, hostname ); //サーバ名(名前またはIP)をszHostへコピー if( isalpha( szHost[0] ) ) { // 名前の場合 hostEnt = gethostbyname( szHost ); //DNSへ問合せ } else { // IPアドレスの場合 addr = inet_addr( szHost ); hostEnt = gethostbyaddr( (char*)&addr, 4, AF_INET ); } if( hostEnt == NULL ) { printf("エラー:アドレスを解決できない [%s]\n・・・終了します\n", szHost); WSACleanup(); return(-1); } printf("サーバを起動させて下さい\n"); printf("起動したらEnterキーを押す"); getchar(); 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) PortNum ); // サーバのポート番号の設定 // サーバへ接続を試みる(connect関数) printf("サーバ[%s]へ接続中...\n", szHost ); if( connect( data_socket,(struct sockaddr*)&server, sizeof(server) ) == SOCKET_ERROR) { printf("エラー:サーバへの接続(connect)\n...終了します\n"); WSACleanup(); return(-1); } printf("%sに接続完了\n", szHost ); // ここからメインルーチン init(); printf("クライアント側が先攻(O)\n"); onArea.x = onArea.y = 0; while(total_fill < grid_size*grid_size){ // 先攻 // ターンの初期化 turn =O_BLACK; rturn = O_WHITE; do{ // 座標情報を受け付ける printf ("縦を入力(1-8): "); scanf ("%d",&onArea.y); printf ("横を入力(1-8): "); scanf ("%d",&onArea.x); onArea.x--; onArea.y--; // 空白のマスか確認 }while(check_empty(onArea)); // 石を返す turn_stone(onArea); // 結果の出力 output(); // データをサーバに送信 // 課題① // 課題① send( data_socket, StrBuf, (int)strlen(StrBuf), 0 ); // ターンの変更 turn =O_WHITE; rturn = O_BLACK; printf("相手の思考待ち\n"); // データの受信 rVal = recv( data_socket, StrBuf, (int)strlen(StrBuf), 0 ); //受信(recv関数) StrBuf[rVal] = '\0'; //受信したデータ(文字列)の最後にNULL文字付加 if( rVal == SOCKET_ERROR || rVal == 0 ) { //受信時エラー(または切断) printf("エラー:相手からの切断されました\n・・・終了します\n"); break; } // 課題② // 課題② // 石を返す turn_stone(onArea); output(); } // ソケット終了処理 closesocket( data_socket ); //ソケットのクローズ WSACleanup(); //ソケットの破棄 printf("\n\nEnterキーを1,2回押してプログラム終了"); getchar(); //プログラム一時停止(キー入力待ち) getchar(); //プログラム一時停止(キー入力待ち) return(0);

}

aaabbbsssaaa, hondamiyu, q22r5695, z22r4875, t44o5862, aaabbbsss, a22r1345, f21l1536, b21a0264, r22e2584, 他1名👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

arcxor

2022/06/20 18:49

至急というのは、いつまでに解答が必要なのでしょうか。
nana_7310

2022/06/20 18:51

6月29日までになります。 具体的な日時の記載をせず申し訳ありません。
退会済みユーザー

退会済みユーザー

2022/06/20 23:06

こういう場所で「至急」とか「6月29日まで」とか書くのは止めた方がいいです。自分のことしか考えてない勝手な人と思われ勝ちなので。
1T2R3M4

2022/06/21 01:04

以下は読まれていないのでしょうか。 https://teratail.com/help/avoid-asking コードをください・デバッグしてください等の丸投げの質問 何かを作りたいのでコードを書いてほしい、学校の課題を解いてほしい等の質問は、具体的にプログラミングで困っている質問ではないと考え、推奨していません。
nana_7310

2022/06/21 01:52

拝読しております。 私としては、丸投げで答えを教えてほしいわけではありませんが、私の書き方によってそう捉えられてしまったのでしたら申し訳ありません。
guest

回答1

0

ベストアンサー

StrBufにはstrlenが適用されているので、NUL終端する必要がある。
Cの配列は0始まり。

投稿2022/06/20 19:41

matukeso

総合スコア1590

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nana_7310

2022/06/21 02:05

NUL終端にしたら完成しました! とても助かりました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問