android socket (소켓통신) 샘플

안드로이드 에뮬레이터를 이용하여 소켓통신을 해보도록 하겠습니다.

서버는 php 로 작성되어 있고

클라이언트는 안드로이드로 접속해보겠습니다.

서버의 포트는 25003 포트를 이용하겠습니다.

server.php

<?php

$host = "0.0.0.0";
$port = 25003;

set_time_limit(0); // no timeout

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n");

$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");

$result = socket_listen($socket, 3) or die("Could not set up socket listener\n");


do {
    $spawn = socket_accept($socket) or die("Could not accept incoming connection\n");

    do {
        $input = socket_read($spawn, 1024) or die("Could not read input\n");

        $input = trim($input);
        echo "Client Message : " . $input . "\n";

        //$response = 'received' . "\n";
        $response = $input ."\n";

        socket_write($spawn, $response, strlen($response)) or die("Could not write output\n");

        if ($input == 'quit') {
            break;
        }
        if ($input == 'shutdown') {
            socket_close($spawn);
            break 2;
        }

    } while (true);
} while (true);
socket_close($socket);

클라이언트 안드로이드 입니다.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Socket_example"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

</manifest>

uses-permission 추가해줍니다.

MainActivity.java

package com.example.socket_example;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class MainActivity extends AppCompatActivity {

    String str;
    String addr;

    String response; //서버 응답

    Handler handler = new Handler(); // 토스트를 띄우기 위한 메인스레드 핸들러 객체 생성

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "Button Clicked", Toast.LENGTH_SHORT).show();
                SocketThread thread = new SocketThread();
                thread.start();

            }
        });
    }

    class SocketThread extends Thread {
        String host;
        String data;
        public SocketThread() {
            this.host = "220.72.212.247";
            this.data = "  1Hello World~~~~";
        }

        @Override
        public void run() {
            try{
                int port = 25003; //포트 번호는 서버측과 똑같이

                Socket socket = new Socket("220.72.212.247", port); // 소켓 열어주기
                ObjectOutputStream outstream = new ObjectOutputStream(socket.getOutputStream()); //소켓의 출력 스트림 참조
                outstream.writeObject(data); // 출력 스트림에 데이터 넣기
                outstream.flush(); // 출력

                ObjectInputStream instream = new ObjectInputStream(socket.getInputStream()); // 소켓의 입력 스트림 참조
                response = (String) instream.readObject(); // 응답 가져오기

                /* 토스트로 서버측 응답 결과 띄워줄 러너블 객체 생성하여 메인스레드 핸들러로 전달 */
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, "서버 응답 : " + response, Toast.LENGTH_LONG).show();
                    }
                });

                socket.close(); // 소켓 해제

            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}