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

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

ただいまの
回答率

89.70%

ソケット通信時に自分が指定したIPアドレスから送信されているか確認がしたい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 708

Ag943

score 8

前提・実現したいこと

C++でソケット通信の学習をしています。
クライアント側でIPアドレスを追加し、BINDでIPアドレスを設定しているつもりなのですが、
ループバックアドレス側の確認用サーバでは"127.0.0.1"から送信されています。
クライアント側のIPアドレスを確認する方法はありますでしょうか?

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

サーバ側のメッセージ

[接続]('127.0.0.1', 52877)

理想

[接続]('192.168.0.101', 52877)

クライアント側

#define MSGSIZE        1024
#define BUFSIZE        (MSGSIZE+1)
/* 
 *ここで設定したIPアドレスで送信が行われているか確認したい 
 */
#define OWNADDR        _T("192.168.0.101")
#define MASK        _T("255.255.255.0")
#define SERVERIP    _T("127.0.0.1")
#define PORT        _T("50001")

//初期設定
int init(void) {
    // winsock機能の初期化
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD(2, 2);
    err = WSAStartup(wVersionRequested, &wsaData);

    CString ownAddr = (OWNADDR);
    CString mask = (MASK);
    CString serverIP = (SERVERIP);
    CString port = (PORT);

    //接続設定
    int rc;
    int lSockfd;
    lSockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    CStringA addrA, ownAddrA;
    addrA = serverIP;        //接続先IP
    ownAddrA = m_addr;        //接続元IP

    //送信元アドレス・ポート番号設定
    struct sockaddr_in myAddr;
    memset(&myAddr, 0, sizeof(myAddr));

    myAddr.sin_family = AF_INET;
    myAddr.sin_port = htons(_ttoi(port));
    inet_pton(AF_INET, ownAddrA, &myAddr.sin_addr.s_addr);

    rc = bind(sockfd, (struct sockaddr *)&myAddr, sizeof(myAddr));

    // 送信先アドレス・ポート番号設定
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    addr.sin_family = AF_INET;
    addr.sin_port = htons(_ttoi(port));
    inet_pton(AF_INET, addrA, &addr.sin_addr.s_addr);

    int connectErr = connect(lSockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
    return lSockfd;
}

//送信処理
bool chatTransmit(CString mes, int sockfd) {

    // データ送信
    CStringA str;

    char send_str[BUFSIZE] = {};

    /* 送信処理 */
    int sendVal = send(sockfd, send_str, strlen(send_str), 0);
    if (sendVal < 0) {
        CString strData = _T("send error :");
        strData.Format(_T("%s%d"), strData, errno);
        AfxMessageBox(strData);
        return false;
    }

    return true;
}

bool chatEnd(int sockfd) {

    shutdown(sockfd, SD_BOTH);
    closesocket(sockfd);
    /* winsock機能の終了 */
    WSACleanup();

    return true;
}

サーバ側(ループバックアドレス)

# -*- coding:utf-8 -*-
import socket
import time
import threading

class socketServer():
    def __init__(self):
        self.host = "127.0.0.1"
        self.port = 50002
        self.clients = []

    def socket_setup(self):   
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind((self.host, self.port))
        sock.listen(10)

        while True:
            print('Waiting for connections...')
            try:
                conn, addr = sock.accept() #接続されればデータを格納
            except KeyboardInterrupt:
                break

            print('testcase1', addr)
            print("[接続]{}".format(addr))
            self.clients.append((conn, addr))

            thread1 = threading.Thread(target=self.socket_send, args=(conn, addr), daemon=True)
            thread2 = threading.Thread(target=self.socket_recv, args=(conn, addr), daemon=True)
            thread1.start()
            thread2.start()

    def close_connection(self, conn, addr):
        print('[切断]{}'.format(addr))
        # 通信を遮断する
        conn.close()

    def socket_send(self, conn, addr):
        cnt = 1
        while True:
            try:        
                time.sleep(1)
                str1 = b'testcase : '
                str2 = str(cnt).encode('utf-8')
                str3 = b'\r\n'
                s_msg = str1 + str2 +str3
                if s_msg == '':
                    self.close_connection(conn, addr)
                    break
                #print('sending...', s_msg)
            except ConnectionResetError:
                self.close_connection(conn, addr)
                break

            cnt = cnt + 1
            try:
                sent = conn.sendall(s_msg) #メッセージを返します
            except ConnectionResetError:
                self.close_connection(conn, addr)
                break

            if sent == 0:
                self.close_connection(conn, addr)
                break
            else:
                print('sending...', s_msg)

    def socket_recv(self, conn, addr):
        while True:
            try:
                # クライアントから送信されたメッセージを 1024 バイトずつ受信
                data = conn.recv(1024)
            except ConnectionResetError:
                # クライアント側でソケットを強制終了(Ctrl + c)すると
                # ソケットサーバが処理落ちするので、コネクションを切断する
                self.close_connection(conn, addr)
                break

            if not data:
                # データが無い場合、接続を切る
                self.close_connection(conn, addr)
                break
            else:
                print('recving... {}, addr&port: {}'.format(data.decode("utf-8"), addr))

                #recv_mes = data.decode()
                #print('message:{}'.format(recv_mes))

#main
ss = socketServer()
ss.socket_setup()

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

クライアント側はMFCで作成のため一部抜粋です。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • t_obara

    2019/07/23 18:04

    貴殿が確認しようとしているのはループバックインターフェースという論理インターフェースに紐づいているので、物理インターフェース経由ではないからかと。別のPCを利用するか、仮想環境などを入れて、それを利用するなどで試してみてはいかがでしょうか。

    キャンセル

  • Ag943

    2019/07/24 08:21

    私はインターフェース回りがよくわかっていないようですね。。別PCは用意できないので、仮想環境を試してみます。ご回答ありがとうございます。

    キャンセル

回答 2

+1

ループバックアドレスへの通信はループバックアドレスから行われます。
192.168.0.101から通信したければ、サーバーも192.168.0.101で立ち上げ、クライアントから192.168.0.101に対して通信してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/24 08:36

    回答ありがとうございます。
    ループバックアドレスを192.168.0.101に変更するとサーバー側が認識できないようです。。。ほかの手段を模索したいと思います。

    キャンセル

  • 2019/07/24 10:04

    self.host = "0.0.0.0"
    でやってみてください。

    キャンセル

checkベストアンサー

0

Wiresharkなどのパケットキャプチャソフトでパケットの生データを見るってのでどうでしょう。
学習用途なら、これしといて損はないと思います

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/24 08:38

    回答ありがとうございます。
    どうも私の環境下ではWiresharkなるものを使うか仮想環境を構築するくらいしか手段がないようです。。。今後のためにもどちらも試行してみます。

    キャンセル

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

  • ただいまの回答率 89.70%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る