今天又是元气满满学习的一天,从上章内容我们可以对socket tcp协议服务端和客户端的简单的信息传递接收进行学习,对socket通信有了一丢丢的了解,
流程图:
总结:tcp socket通信主要是再InputStream 和 OutputStream之间进行数据的读取和写入
其中我们可以通过 socket.getInputStream() 或者 socket.getOutputStream()拿到实例 然后进行读取和写入的功能
其中 socket.getInputStream()为输入流(读取) 收到的数据在这里
socket.getOutputStream()为输出流(写入) 发送的数据在这里
好了,废话不多比比 开始我们的简易聊天室的实现 —> 详细的实现请看代码中的注释
eclipse 服务端
public class Server {
public static final int PORT = 12345;//端口号
private List<Socket> mList = new ArrayList<Socket>();
private ServerSocket server = null;
private ExecutorService myExecutorService = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
new Server();
}
public Server(){
//服务器创建流程如下
try {
//1.创建ServerSocket
server = new ServerSocket(PORT);
//创建线程池
myExecutorService = Executors.newCachedThreadPool();
System.out.println("服务端运行中...\n");
Socket client = null;
while(true)
{
//2.等待接收请求 这里接收客户端的请求
client = server.accept();
System.out.println("得到客户端连接:" + client);
mList.add(client);
//初始化完成
//执行线程
myExecutorService.execute(new Service(client));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class Service implements Runnable{
private Socket socket;
private BufferedReader in = null;
private String msg = "";
public Service(Socket socket){
this.socket = socket;
try {
//3.接收请求后创建链接socket
//4.通过InputStream outputStream进行通信
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//可拆分
// InputStream is = socket.getInputStream();
//
// InputStreamReader ins = new InputStreamReader(is);
//
// in = new BufferedReader(ins);
msg = "用户:" +this.socket.getInetAddress() + "~加入了聊天室"
+"当前在线人数:" +mList.size();
this.sendmsg();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
if((msg=in.readLine())!=null){
System.out.println("从客户端接收到的消息为:" + msg);
if(msg.equals("bye")){
System.out.println("~~~~~~~~~~~~~");
mList.remove(socket);
in.close();
msg = "用户:" + socket.getInetAddress()
+ "退出:" +"当前在线人数:"+mList.size();
//5.关闭资源
socket.close();
this.sendmsg();
break;
}else{
msg = socket.getInetAddress() + " 说: " + msg;
this.sendmsg();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//为连接上服务端的每个客户端发送信息
public void sendmsg()
{
System.out.println(msg);
int num = mList.size();
for(int index = 0;index < num;index++)
{
Socket mSocket = mList.get(index);
PrintWriter pout = null;
try {
//PrintWriter 和BufferWriter使用方法相似
pout = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(mSocket.getOutputStream(),"UTF-8")),true);
pout.println(msg); //将输出流包装为打印流
}catch (IOException e) {e.printStackTrace();}
}
}
}
}
从上面的服务器端我们可以知道服务器端先将客户端发送的数据进行存储到msg中 然后通过PrintWriter 又发送到了客户端
PrintWriter 详解:
//PrintWriter 和BufferWriter使用区别
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bufw.write("hello,server!");
bufw.newLine();
bufw.flush();
//上面的4行代码用PrintWriter实现只需要两行。
PrintWtriter out = new PrintWriter(s.getOutputStream, true);
out.println("hello,server!");
安卓客户端
public class ChatRoom extends AppCompatActivity implements Runnable{
//定义相关变量,完成初始化
private TextView txtshow;
private EditText editsend;
private Button btnsend;
private static final String HOST = "192.168.30.83";
private static final int PORT = 12345;
private Socket socket = null;
private BufferedReader in = null;
private PrintWriter out = null;
private String content = "";
private StringBuilder sb = null;
//定义一个handler对象,用来刷新界面
public Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
sb.append(content);
Log.i("wotainanl","@@"+sb);
txtshow.setText(sb.toString());
}
}
;
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat_room);
sb = new StringBuilder();
txtshow = findViewById(R.id.txtshow);
editsend = findViewById(R.id.editsend);
btnsend = findViewById(R.id.btnsendza);
//当程序一开始运行的时候就实例化Socket对象,与服务端进行连接,获取输入输出流
new Thread() {
public void run() {
try {
socket = new Socket(HOST, PORT);
//获取输入输出流
in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
Log.i("wotainanl","in"+in+"@@"+out);
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
// 为发送按钮设置点击事件
btnsend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String msg = editsend.getText().toString();
if (socket.isConnected()) {
if (!socket.isOutputShutdown()) {
new Thread(new Runnable() {
@Override
public void run() {
out.println(msg);
}
}).start();
Log.i("wotainanl",msg);
}
}
}
});
new Thread(ChatRoom.this).start();
}
//重写run方法,在该方法中输入流的读取
@Override
public void run() {
try {
while (true) {
if (socket.isConnected()) {
if (!socket.isInputShutdown()) {
if ((content = in.readLine()) != null) {
content += "\n";
handler.sendEmptyMessage(0x123);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
over!
Socket TCP的通信流程:
传输前先开服务端,accept,等客户端接入,然后获得 客户端socket然后进行IO操作
本文参考:https://www.kancloud.cn/kancloud/android-tutorial/87240