Skip to content

Commit d07a6a5

Browse files
committed
feat: first commit
1 parent 9933d85 commit d07a6a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1413
-0
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.iml
2+
.gradle
3+
/local.properties
4+
/.idea
5+
.DS_Store
6+
/build
7+
/captures
8+
.externalNativeBuild

RxSocketClient/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

RxSocketClient/build.gradle

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apply plugin: 'java-library'
2+
apply plugin: 'kotlin'
3+
4+
dependencies {
5+
implementation fileTree(dir: 'libs', include: ['*.jar'])
6+
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
7+
compile "io.reactivex.rxjava2:rxjava:2.1.1"
8+
}
9+
10+
sourceCompatibility = "1.7"
11+
targetCompatibility = "1.7"
12+
buildscript {
13+
ext.kotlin_version = '1.1.3-2'
14+
repositories {
15+
mavenCentral()
16+
}
17+
dependencies {
18+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
19+
}
20+
}
21+
repositories {
22+
mavenCentral()
23+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (C) 2017 codeestX
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package moe.codeest.rxsocketclient
18+
19+
import moe.codeest.rxsocketclient.meta.SocketConfig
20+
21+
/**
22+
* @author: Est <[email protected]>
23+
* @date: 2017/7/8
24+
* @description:
25+
*/
26+
27+
class RxSocketClient {
28+
29+
companion object {
30+
@JvmStatic fun create(config: SocketConfig) : SocketClient = SocketClient(config)
31+
}
32+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright (C) 2017 codeestX
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package moe.codeest.rxsocketclient
18+
19+
import io.reactivex.Observable
20+
import moe.codeest.rxsocketclient.meta.DataWrapper
21+
import moe.codeest.rxsocketclient.meta.SocketConfig
22+
import moe.codeest.rxsocketclient.meta.SocketOption
23+
import moe.codeest.rxsocketclient.meta.ThreadStrategy
24+
import moe.codeest.rxsocketclient.post.AsyncIPoster
25+
import moe.codeest.rxsocketclient.post.IPoster
26+
import moe.codeest.rxsocketclient.post.SyncIPoster
27+
import java.net.Socket
28+
import java.util.concurrent.Executor
29+
import java.util.concurrent.Executors
30+
import java.util.concurrent.TimeUnit
31+
32+
/**
33+
* @author: Est <[email protected]>
34+
* @date: 2017/7/9
35+
* @description:
36+
*/
37+
38+
class SocketClient(val mConfig: SocketConfig) {
39+
40+
var mSocket: Socket = Socket()
41+
var mOption: SocketOption? = null
42+
lateinit var mObservable: Observable<DataWrapper>
43+
lateinit var mIPoster: IPoster
44+
var mExecutor: Executor = Executors.newCachedThreadPool()
45+
46+
fun option(option: SocketOption): SocketClient {
47+
mOption = option
48+
return this
49+
}
50+
51+
fun connect(): Observable<DataWrapper> {
52+
mObservable = SocketObservable(mConfig, mSocket)
53+
mIPoster = if (mConfig.mThreadStrategy == ThreadStrategy.ASYNC) AsyncIPoster(this, mExecutor) else SyncIPoster(this, mExecutor)
54+
initHeartBeat()
55+
return mObservable
56+
}
57+
58+
fun disconnect() {
59+
if (mObservable is SocketObservable) {
60+
(mObservable as SocketObservable).close()
61+
}
62+
}
63+
64+
private fun initHeartBeat() {
65+
mOption?.apply {
66+
if (mHeartBeatConfig != null) {
67+
val disposable = Observable.interval(mHeartBeatConfig.interval, TimeUnit.MILLISECONDS)
68+
.subscribe({
69+
sendData(mHeartBeatConfig.data?: ByteArray(0))
70+
})
71+
if (mObservable is SocketObservable) {
72+
(mObservable as SocketObservable).setHeartBeatRef(disposable)
73+
}
74+
}
75+
}
76+
}
77+
78+
fun sendData(data: ByteArray) {
79+
mOption?.apply {
80+
if (mHead != null || mTail != null) {
81+
var result: String = data.toString()
82+
mHead?.let {
83+
if (mHead.isNotEmpty()) {
84+
mHead.toString().plus(result)
85+
}
86+
}
87+
mTail?.let {
88+
if (mTail.isNotEmpty()) {
89+
result.plus(mTail.toString())
90+
}
91+
}
92+
mIPoster.enqueue(result.toByteArray(charset = mConfig.mCharset))
93+
return@sendData
94+
}
95+
}
96+
mIPoster.enqueue(data)
97+
}
98+
99+
fun sendData(string: String) {
100+
sendData(string.toByteArray(charset = mConfig.mCharset))
101+
}
102+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright (C) 2017 codeestX
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package moe.codeest.rxsocketclient
18+
19+
import io.reactivex.Observable
20+
import io.reactivex.Observer
21+
import io.reactivex.disposables.Disposable
22+
import moe.codeest.rxsocketclient.meta.DataWrapper
23+
import moe.codeest.rxsocketclient.meta.SocketConfig
24+
import java.net.InetSocketAddress
25+
import java.net.Socket
26+
import moe.codeest.rxsocketclient.meta.SocketState
27+
import java.io.DataInputStream
28+
import java.io.IOException
29+
30+
31+
/**
32+
* @author: Est <[email protected]>
33+
* @date: 2017/7/9
34+
* @description:
35+
*/
36+
37+
class SocketObservable(val mConfig: SocketConfig, val mSocket: Socket) : Observable<DataWrapper>() {
38+
39+
val mReadThread: ReadThread = ReadThread()
40+
lateinit var observerWrapper: SocketObserver
41+
var mHeartBeatRef: Disposable? = null
42+
43+
override fun subscribeActual(observer: Observer<in DataWrapper>?) {
44+
observerWrapper = SocketObserver(observer)
45+
observer?.onSubscribe(observerWrapper)
46+
47+
try {
48+
Thread(Runnable {
49+
mSocket.connect(InetSocketAddress(mConfig.mIp, mConfig.mPort?: 1080), mConfig.mTimeout?: 0)
50+
observer?.onNext(DataWrapper(SocketState.OPEN, ByteArray(0)))
51+
mReadThread.start()
52+
}).start()
53+
} catch (e: IOException) {
54+
println(e.toString())
55+
observer?.onNext(DataWrapper(SocketState.CLOSE, ByteArray(0)))
56+
}
57+
}
58+
59+
fun setHeartBeatRef(ref: Disposable) {
60+
mHeartBeatRef = ref
61+
}
62+
63+
fun close() {
64+
observerWrapper.dispose()
65+
}
66+
67+
inner class SocketObserver(private val observer: Observer<in DataWrapper>?) : Disposable {
68+
69+
fun onNext(data: ByteArray) {
70+
if (mSocket.isConnected) {
71+
observer?.onNext(DataWrapper(SocketState.CONNECTING, data))
72+
}
73+
}
74+
75+
fun onNext(dataWrapper: DataWrapper) {
76+
if (mSocket.isConnected) {
77+
observer?.onNext(dataWrapper)
78+
}
79+
}
80+
81+
override fun dispose() {
82+
mReadThread.interrupt()
83+
mHeartBeatRef?.dispose()
84+
mSocket.close()
85+
observer?.onNext(DataWrapper(SocketState.CLOSE, ByteArray(0)))
86+
}
87+
88+
override fun isDisposed(): Boolean {
89+
return mSocket.isConnected
90+
}
91+
}
92+
93+
inner class ReadThread : Thread() {
94+
override fun run() {
95+
super.run()
96+
try {
97+
while (!mReadThread.isInterrupted && mSocket.isConnected) {
98+
val input = DataInputStream(mSocket.getInputStream())
99+
var buffer: ByteArray = ByteArray(input.available())
100+
if (buffer.isNotEmpty()) {
101+
input.read(buffer)
102+
observerWrapper.onNext(buffer)
103+
}
104+
}
105+
}catch (e: Exception) {
106+
107+
}
108+
}
109+
}
110+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (C) 2017 codeestX
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package moe.codeest.rxsocketclient
18+
19+
import io.reactivex.functions.Consumer
20+
import moe.codeest.rxsocketclient.meta.DataWrapper
21+
import moe.codeest.rxsocketclient.meta.SocketState
22+
23+
24+
/**
25+
* @author: Est <[email protected]>
26+
* @date: 2017/7/9
27+
* @description:
28+
*/
29+
30+
abstract class SocketSubscriber : Consumer<DataWrapper> {
31+
32+
override fun accept(t: DataWrapper) {
33+
when (t.state) {
34+
SocketState.CONNECTING -> onResponse(t.data)
35+
SocketState.OPEN -> onConnected()
36+
SocketState.CLOSE -> onDisconnected()
37+
}
38+
39+
}
40+
41+
abstract fun onConnected()
42+
43+
abstract fun onDisconnected()
44+
45+
abstract fun onResponse(data: ByteArray)
46+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (C) 2017 codeestX
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package moe.codeest.rxsocketclient.meta
18+
19+
/**
20+
* @author: Est <[email protected]>
21+
* @date: 2017/7/8
22+
* @description:
23+
*/
24+
object SocketState {
25+
26+
const val OPEN = 0x00
27+
28+
const val CONNECTING = 0x01
29+
30+
const val CLOSE = 0x02
31+
}
32+
33+
object ThreadStrategy {
34+
35+
const val SYNC = 0x00
36+
37+
const val ASYNC = 0x01
38+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (C) 2017 codeestX
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package moe.codeest.rxsocketclient.meta
18+
19+
/**
20+
* @author: Est <[email protected]>
21+
* @date: 2017/7/8
22+
* @description:
23+
*/
24+
25+
data class DataWrapper(val state: Int, val data: ByteArray)

0 commit comments

Comments
 (0)