实现场景:手机A作为客户端,手机B作为服务端,通过Socket实现信息交互与处理。
如下图:客户端通过ip和端口连接服务器,客户端发送hello,服务端接收后,处理成大写发送给客户端,通过Toast显示
虽然是个简单的测试,但基本涵盖了Socket编程的所有基础知识
页面布局
socket编程1png服务端显示效果
socket编程2.png打开服务以及有设备加入时,界面上的反应
socket编程.png
一、服务端实现
1.服务端界面:TCPServerActivity.java
1.通过
ServerSocket
开启服务
2.将连接的客户端显示在服务端界面
3.为该客户端开启服务线程
case R.id.id_btn_start_server://开启服务
new Thread(() -> {
try {
//1.开启服务器
ServerSocket serverSocket = new ServerSocket(8080);
runOnUiThread(() -> mIdTvLink.setText("服务已开启"));
mJoinRunnable = new JoinRunnable(serverSocket);
//2.将连接的客户端显示在服务端界面
mJoinRunnable.setOnConnListener(ip -> runOnUiThread(() -> {
mIdTvLink.append("\n" + ip + "已连接");
}));
//3.为该客户端开启服务线程
new Thread(mJoinRunnable).start();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
break;
case R.id.id_btn_close_server://关闭服务
if (mJoinRunnable != null) {
mIdTvLink.setText("服务未开启");
mJoinRunnable.close();
}
break;
2.JoinRunnable:每次客户端加入时创建的线程
1.通过服务端ServerSocket获取Socket对象
2.获取连接的客户端ip,并设置连接时的回调监听
3.通过Socket获取输入I流,读取客户端的信息
4.通过Socket获取输出O流,向客户端发送信息
5.进行IO流操作
/**
* 作者:张风捷特烈<br/>
* 时间:2018/10/14 0014:8:01<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:每次客户端加入时创建的线程
*/
public class JoinRunnable implements Runnable {
private ServerSocket mServerSocket;//ServerSocket对象
private Socket mSocket;//Socket对象
public JoinRunnable(ServerSocket serverSocket) {
mServerSocket = serverSocket;
}
@Override
public void run() {
InputStream is = null;
OutputStream os = null;
try {
//1.通过服务端ServerSocket获取Socket对象
mSocket = mServerSocket.accept();
//2.获取连接的客户端ip,并设置连接时的回调监听
String ip = mSocket.getInetAddress().getHostAddress();
if (mOnConnListener != null) {
mOnConnListener.conn(ip);
}
//3.通过Socket获取输入I流,读取客户端的信息
is = mSocket.getInputStream();
//4.通过Socket获取输出O流,向客户端发送信息
os = mSocket.getOutputStream();
//5.IO操作
int len = 0;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
String msg = new String(buf, 0, len).toUpperCase();
//将读出来的信息进行操作后返回给客户端
os.write(("服务端发来信息:" + msg).getBytes());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 关闭客户端连接
*/
public void close() {
try {
mServerSocket.close();
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//客户端连接时的监听
public interface OnConnListener {
void conn(String ip);
}
private OnConnListener mOnConnListener;
public void setOnConnListener(OnConnListener onConnListener) {
mOnConnListener = onConnListener;
}
}
二、客户端页:
@OnClick({R.id.id_btn_send, R.id.id_btn_setip})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.id_btn_setip:
//通过ip和端口连接服务端
new Thread(() -> connServer(mIdEtIp.getText().toString(), 8080)).start();
break;
case R.id.id_btn_send:
//将键盘输入内容发送给服务端
mPwOut.println(mIdTcp.getText());
break;
}
}
/**
* 通过ip和端口连接服务端核心代码
*
* @param ip ip地址
* @param port 端口
*/
private void connServer(String ip, int port) {
try {
//1.创建客户端Socket对象(ip,端口)
mSocket = new Socket(ip, port);
//2.通过socket对象获取字节输出流,并包装成PrintWriter----用于发送给服务端数据
mPwOut = new PrintWriter(mSocket.getOutputStream(), true);
//3.通过socket对象获取字节输出流
InputStream is = mSocket.getInputStream();
int len = 0;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
msg = new String(buf, 0, len).toUpperCase();
runOnUiThread(() -> ToastUtil.showAtOnce(TCPClientActivity.this, msg));
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
后记:捷文规范
1.本文成长记录及勘误表
项目源码 | 日期 | 备注 |
---|---|---|
V0.1--无 | 2018-10-15 | 2--安卓网络编程之http协议简介+小案例引入 |
2.更多关于我
笔名 | 微信 | 爱好 | |
---|---|---|---|
张风捷特烈 | 1981462002 | zdl1994328 | 语言 |
我的github | 我的简书 | 我的CSDN | 个人网站 |
3.声明
1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持
网友评论