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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

TCP

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

Q&A

解決済

2回答

1438閲覧

TCP通信で受信データ表示時に0になってしまう

mmmw

総合スコア23

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

TCP

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

0グッド

0クリップ

投稿2019/10/25 00:30

編集2019/10/25 00:55

前提・実現したいこと

ソケット通信プログラムで測定データの送受信を行いたい
受信側で受信した測定データが0になってしまう

発生している問題・エラーメッセージ

クライアント側で受け取り表示するデータが0になってしまう

該当のソースコード

C++

1 2//クライアント側 3 4 5 6 7VOID DisplayFrame( PBYTE pBuf, DWORD dwSize ) 8{ 9 //TCP 10 11 char server_ip_addr[32]; 12 13 int port_number; 14 15 16 17 // Windows Sockets仕様に関する情報を格納する構造体 18 19 WSADATA wsa_data; 20 21 // WinSockの初期化処理(Version 2.0) 22 23 if (WSAStartup(MAKEWORD(2, 0), &wsa_data) != 0) { 24 25 std::cerr << "Winsockの初期化失敗(WSAStartup)" << std::endl; 26 27 } 28 29 30 31 // ユーザ入力 32 33 std::cout << "接続先IPアドレスを入力してください(xxx.xxx.xxx.xxx)" << std::endl; 34 35 std::cin >> server_ip_addr; 36 37 std::cout << "ポート番号を入力してください" << std::endl; 38 39 std::cin >> port_number; 40 41 42 43 // sockaddr_in構造体の作成とポート番号、IPタイプの入力 44 45 struct sockaddr_in dst_addr; 46 47 memset(&dst_addr, 0, sizeof(dst_addr)); 48 49 dst_addr.sin_port = htons(port_number); // ポート番号 50 51 dst_addr.sin_family = AF_INET; // AF_INETはipv4を示す 52 53 54 55 // 引数は (1) Type(ipv4 or v6) (2) IPアドレスのテキスト形式 (3) IPアドレスのバイナリ形式【(2)→(3)に変換】 56 57 inet_pton(dst_addr.sin_family, server_ip_addr, &dst_addr.sin_addr.s_addr); 58 59 60 61 // AF_INETはipv4のIPプロトコル & SOCK_STREAMはTCPプロトコル 62 63 int dst_socket = socket(AF_INET, SOCK_STREAM, 0); 64 65 66 67 // 接続処理 68 69 if (connect(dst_socket, (struct sockaddr *) &dst_addr, sizeof(dst_addr))) { 70 71 std::cerr << "接続失敗(サーバIPアドレス" << server_ip_addr << "/接続先ポート番号" << port_number << std::endl; 72 73 exit(0); 74 75 } 76 77 78 79 std::cout << "接続完了(サーバIPアドレス" << server_ip_addr << "/接続先ポート番号" << port_number << std::endl << std::endl;; 80 81 82 83 84 85 char send_buf1[256]; 86 87 char recv_buf[256]; 88 89 90 91 92 93 TCHAR szFrame[200]; 94 DWORD i = 0; 95 96 while ( i<dwSize) 97 { 98 BYTE ucSensor = pBuf[i+2]; 99 SHORT shSize = pBuf[i+6]; 100 101 // skip rest of header 102 i += 8; 103 104 PDWORD pFC = (PDWORD)(&pBuf[i]); 105 PFLOAT pPno = (PFLOAT)(&pBuf[i+4]); 106 107 _sntprintf( szFrame, _countof(szFrame), _T("%2d %d %+011.6f %+011.6f %+011.6f %+011.6f %+011.6f %+011.6ff\r"), 108 ucSensor, *pFC, pPno[0], pPno[1], pPno[2], pPno[3], pPno[4], pPno[5] ); 109 tstring sF = tstring(szFrame); 110 if (g_bScroll) 111 sF += tstring(_T("\n")); 112 113 114 115 //TCP 116 117 // Packetの送信(SOCKET, Buffer, Datasize, 送信方法) 118 send_buf1[256] = pPno[5]; 119 120 send(dst_socket, send_buf1, 256, 0); 121 122 // Packetの受信 123 124 recv(dst_socket, recv_buf, 256, 0); 125 126 127 128 AddMsg( sF ); 129 130 i += shSize; 131 } 132 133 // 解放処理 134 135 closesocket(dst_socket); 136 137 138 139 // WinSockの終了処理 140 141 WSACleanup(); 142} 143 144 145 146 147/////////////////////////////////////////////////////////////////////// 148/////////////////////////////////////////////////////////////////////// 149 150 151 152 153// サーバ側 WinSock2 154 155 156 157#include <stdio.h> 158 159#include <winsock2.h> 160 161#include <ws2tcpip.h> 162 163#include <iostream> 164 165 166 167int main() { 168 169 170 171 // ポート番号 172 173 int port_number = 12345; 174 175 176 177 // Windows Sockets仕様に関する情報を格納する構造体 178 179 WSADATA wsa_data; 180 181 182 183 // WinSockの初期化処理(Version 2.0) 184 185 if (WSAStartup(MAKEWORD(2, 0), &wsa_data) != 0) { 186 187 std::cerr << "Winsockの初期化失敗(WSAStartup)" << std::endl; 188 189 } 190 191 192 193 // サーバ側ソケット作成 194 195 int src_socket; 196 197 198 199 // sockaddr_in構造体の作成とポート番号、IPタイプの入力 200 201 struct sockaddr_in src_addr; 202 203 memset(&src_addr, 0, sizeof(src_addr)); 204 205 src_addr.sin_port = htons(port_number); 206 207 src_addr.sin_family = AF_INET; 208 209 src_addr.sin_addr.s_addr = htonl(INADDR_ANY); 210 211 212 213 // AF_INETはipv4のIPプロトコル & SOCK_STREAMはTCPプロトコル 214 215 src_socket = socket(AF_INET, SOCK_STREAM, 0); 216 217 218 219 // サーバ側のソケットを特定のIPアドレスとポートに紐付ける 220 221 bind(src_socket, (struct sockaddr *) &src_addr, sizeof(src_addr)); 222 223 224 225 // クライアント側のソケット設定 226 227 int dst_socket; 228 229 struct sockaddr_in dst_addr; 230 231 int dst_addr_size = sizeof(dst_addr); 232 233 234 235 // 接続の待受を開始する 236 237 listen(src_socket, 1); 238 239 240 241 // 送受信に使用するバッファ 242 243 char recv_buf1[257], recv_buf2[257]; 244 245 char send_buf[257]; 246 247 248 249 // クライアントからの接続待ちループ関数 250 251 while (1) { 252 253 254 255 std::cout << "クライアントからの接続待ち" << std::endl; 256 257 258 259 // クライアントからの接続を受信する 260 261 dst_socket = accept(src_socket, (struct sockaddr *) &dst_addr, &dst_addr_size); 262 263 264 265 std::cout << "クライアントからの接続有り" << std::endl; 266 267 268 269 // 接続後の処理 270 271 while (1) { 272 273 274 275 int status; 276 277 278 279 //パケットの受信(recvは成功すると受信したデータのバイト数を返却。切断で0、失敗で-1が返却される 280 281 int recv1_result = recv(dst_socket, recv_buf1, sizeof(char) * 256, 0); 282 283 if (recv1_result == 0 || recv1_result == -1) { 284 285 status = closesocket(dst_socket); break; 286 287 } 288 289 //std::cout << atoi(recv_buf1) << std::endl; ..... ※ 290 std::cout << strtol(recv_buf1,NULL,0) << std::endl; 291 292 send(dst_socket, send_buf, sizeof(char) * 256, 0); 293 294 } 295 296 } 297 298 299 300 // WinSockの終了処理 301 302 WSACleanup(); 303 304 305 306 return 0; 307 308} 309

試したこと

サーバー側ソースコードで※のところにatoi や strtolを試してみた

補足情報(FW/ツールのバージョンなど)

visual C++

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

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

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

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

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

guest

回答2

0

ベストアンサー

まず、sendrecv API(関数)の返り値は無視しないでください。無視していたら本当に送信できたのか、受信できたのか分かりません。sendの返り値は送信できたバイト数またはエラーを示す値であり、recvの返り値は受信できたバイト数またはエラーを示す値です。さらに、recvの返り値が0の場合は「リモート側からコネクションが切断された」が通例です。問題解決の話はそれからだと思います。

Microsoft Docs - send
同 - recv

投稿2019/10/25 01:15

dodox86

総合スコア9183

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

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

mmmw

2019/10/25 02:15

すいません。 具体的にはどのようにすればよいのでしょうか。
dodox86

2019/10/25 02:22

int ret = recv(dst_socket、いろいろ); if (ret > 0) { // 受信できているので、受信したバッファの内容を処理する。 } else if (ret < 0) { //エラーが起きた } else { // ret == 0 恐らくコネクションが切れてる。 // クライアント側ならこれ以降受信できないので、終了して良い。 } のようなかんじになるかと思います。1から10までは書けないので、「C言語 ソケットプログラミング」などと検索して、調べてみてください。
dodox86

2019/10/25 02:30

WinSockなので、少し訂正します。 int ret = recv(dst_socket、いろいろ); if (ret > 0) { // 受信できているので、受信したバッファの内容を処理する。 } else if (ret == 0) { // コネクションが切れてる。クライアント側ならこれ以降受信できないので、終了して良い。 } else { // ret == SOCKET_ERROR // エラーが起きたので、エラー処理 } の方がコード的には適切かもしれません。実質、同じですが。
mmmw

2019/10/25 02:56

すみません。 ご丁寧にありがとうございます。 試してみます。
guest

0

まずは受信した文字列を表示させて、どういう文字列が受信されているか見てみればどうでしょう

投稿2019/10/25 00:37

y_waiwai

総合スコア87747

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

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

mmmw

2019/10/25 00:52

文字列を表示してみたところ フフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフ と表示されました...
mmmw

2019/10/25 00:58

クライアント側プログラム  // Packetの送信(SOCKET, Buffer, Datasize, 送信方法) send_buf1[256] = pPno[5]; の部分でC4244 '=' 'FLOAT' から 'char' の変換です。データが失われる可能性があります という警告は関係するのでしょうか。
y_waiwai

2019/10/25 01:04

それは関係しません。 そもそも、 > send_buf1[256] = pPno[5]; > send(dst_socket, send_buf1, 256, 0); send_buf1にはなにもデータは設定されてません なにを送信しようとしてるんでしょう
mmmw

2019/10/25 01:12

pPno[5]に測定データが格納されていると思うのですが, それを,send_buf1[256]に入れなおして送信しようと思っています 初心者で滅茶苦茶なことをしていたら,すいません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問