├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── scut │ │ └── carson_ho │ │ └── socket_carson │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── scut │ │ │ └── carson_ho │ │ │ └── socket_carson │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── scut │ └── carson_ho │ └── socket_carson │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Socket_Carson -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Android 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 62 | 63 | 64 | 65 | 66 | 1.8 67 | 68 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "24.0.2" 6 | 7 | defaultConfig { 8 | applicationId "scut.carson_ho.socket_carson" 9 | minSdkVersion 19 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | } 27 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/Carson_Ho/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/scut/carson_ho/socket_carson/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package scut.carson_ho.socket_carson; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/scut/carson_ho/socket_carson/MainActivity.java: -------------------------------------------------------------------------------- 1 | package scut.carson_ho.socket_carson; 2 | 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.os.Message; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.EditText; 10 | import android.widget.TextView; 11 | 12 | import java.io.BufferedReader; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.io.InputStreamReader; 16 | import java.io.OutputStream; 17 | import java.net.Socket; 18 | import java.util.concurrent.ExecutorService; 19 | import java.util.concurrent.Executors; 20 | 21 | public class MainActivity extends AppCompatActivity { 22 | 23 | /** 24 | * 主 变量 25 | */ 26 | 27 | // 主线程Handler 28 | // 用于将从服务器获取的消息显示出来 29 | private Handler mMainHandler; 30 | 31 | // Socket变量 32 | private Socket socket; 33 | 34 | // 线程池 35 | // 为了方便展示,此处直接采用线程池进行线程管理,而没有一个个开线程 36 | private ExecutorService mThreadPool; 37 | 38 | /** 39 | * 接收服务器消息 变量 40 | */ 41 | // 输入流对象 42 | InputStream is; 43 | 44 | // 输入流读取器对象 45 | InputStreamReader isr ; 46 | BufferedReader br ; 47 | 48 | // 接收服务器发送过来的消息 49 | String response; 50 | 51 | 52 | /** 53 | * 发送消息到服务器 变量 54 | */ 55 | // 输出流对象 56 | OutputStream outputStream; 57 | 58 | /** 59 | * 按钮 变量 60 | */ 61 | 62 | // 连接 断开连接 发送数据到服务器 的按钮变量 63 | private Button btnConnect, btnDisconnect, btnSend; 64 | 65 | // 显示接收服务器消息 按钮 66 | private TextView Receive,receive_message; 67 | 68 | // 输入需要发送的消息 输入框 69 | private EditText mEdit; 70 | 71 | 72 | 73 | 74 | 75 | @Override 76 | protected void onCreate(Bundle savedInstanceState) { 77 | super.onCreate(savedInstanceState); 78 | setContentView(R.layout.activity_main); 79 | 80 | /** 81 | * 初始化操作 82 | */ 83 | 84 | // 初始化所有按钮 85 | btnConnect = (Button) findViewById(R.id.connect); 86 | btnDisconnect = (Button) findViewById(R.id.disconnect); 87 | btnSend = (Button) findViewById(R.id.send); 88 | mEdit = (EditText) findViewById(R.id.edit); 89 | receive_message = (TextView) findViewById(R.id.receive_message); 90 | Receive = (Button) findViewById(R.id.Receive); 91 | 92 | // 初始化线程池 93 | mThreadPool = Executors.newCachedThreadPool(); 94 | 95 | 96 | // 实例化主线程,用于更新接收过来的消息 97 | mMainHandler = new Handler() { 98 | @Override 99 | public void handleMessage(Message msg) { 100 | switch (msg.what) { 101 | case 0: 102 | receive_message.setText(response); 103 | break; 104 | } 105 | } 106 | }; 107 | 108 | 109 | /** 110 | * 创建客户端 & 服务器的连接 111 | */ 112 | btnConnect.setOnClickListener(new View.OnClickListener() { 113 | @Override 114 | public void onClick(View v) { 115 | 116 | // 利用线程池直接开启一个线程 & 执行该线程 117 | mThreadPool.execute(new Runnable() { 118 | @Override 119 | public void run() { 120 | 121 | try { 122 | 123 | // 创建Socket对象 & 指定服务端的IP 及 端口号 124 | socket = new Socket("192.168.1.172", 8989); 125 | 126 | // 判断客户端和服务器是否连接成功 127 | System.out.println(socket.isConnected()); 128 | 129 | } catch (IOException e) { 130 | e.printStackTrace(); 131 | } 132 | 133 | } 134 | }); 135 | 136 | } 137 | }); 138 | 139 | /** 140 | * 接收 服务器消息 141 | */ 142 | Receive.setOnClickListener(new View.OnClickListener() { 143 | @Override 144 | public void onClick(View v) { 145 | 146 | // 利用线程池直接开启一个线程 & 执行该线程 147 | mThreadPool.execute(new Runnable() { 148 | @Override 149 | public void run() { 150 | 151 | try { 152 | // 步骤1:创建输入流对象InputStream 153 | is = socket.getInputStream(); 154 | 155 | // 步骤2:创建输入流读取器对象 并传入输入流对象 156 | // 该对象作用:获取服务器返回的数据 157 | isr = new InputStreamReader(is); 158 | br = new BufferedReader(isr); 159 | 160 | // 步骤3:通过输入流读取器对象 接收服务器发送过来的数据 161 | response = br.readLine(); 162 | 163 | // 步骤4:通知主线程,将接收的消息显示到界面 164 | Message msg = Message.obtain(); 165 | msg.what = 0; 166 | mMainHandler.sendMessage(msg); 167 | 168 | } catch (IOException e) { 169 | e.printStackTrace(); 170 | } 171 | 172 | } 173 | }); 174 | 175 | } 176 | }); 177 | 178 | 179 | /** 180 | * 发送消息 给 服务器 181 | */ 182 | btnSend.setOnClickListener(new View.OnClickListener() { 183 | @Override 184 | public void onClick(View v) { 185 | 186 | // 利用线程池直接开启一个线程 & 执行该线程 187 | mThreadPool.execute(new Runnable() { 188 | @Override 189 | public void run() { 190 | 191 | try { 192 | // 步骤1:从Socket 获得输出流对象OutputStream 193 | // 该对象作用:发送数据 194 | outputStream = socket.getOutputStream(); 195 | 196 | // 步骤2:写入需要发送的数据到输出流对象中 197 | outputStream.write((mEdit.getText().toString()+"\n").getBytes("utf-8")); 198 | // 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞 199 | 200 | // 步骤3:发送数据到服务端 201 | outputStream.flush(); 202 | 203 | } catch (IOException e) { 204 | e.printStackTrace(); 205 | } 206 | 207 | } 208 | }); 209 | 210 | } 211 | }); 212 | 213 | 214 | /** 215 | * 断开客户端 & 服务器的连接 216 | */ 217 | btnDisconnect.setOnClickListener(new View.OnClickListener() { 218 | @Override 219 | public void onClick(View v) { 220 | 221 | try { 222 | // 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStream 223 | outputStream.close(); 224 | 225 | // 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReader 226 | br.close(); 227 | 228 | // 最终关闭整个Socket连接 229 | socket.close(); 230 | 231 | // 判断客户端和服务器是否已经断开连接 232 | System.out.println(socket.isConnected()); 233 | 234 | } catch (IOException e) { 235 | e.printStackTrace(); 236 | } 237 | 238 | } 239 | }); 240 | 241 | 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |