版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/AmazingUU/article/details/52567036
效果图:
利用socket实现了简单的聊天室功能。首先要用java先写一个ServerSocket服务器
public class SocketTest {
public static void main(String[] args) {
try {
//端口号从1-65535中任选一个,一般选择较大的
ServerSocket serverSocket= new ServerSocket(12346);
//阻塞线程
Socket socket=serverSocket.accept();
System.out.println("success");
} catch (IOException e) {
e.printStackTrace();
}
}
}
上面一段代码就可以创建一个ServerSocket服务器端,在浏览器里输入本机IP再加上端口号(我的是192.168.56.1:12346),就可以在android studio里看到success,代表连接成功.(浏览器里为什么会显示无法连接,可能是因为我没有写网页的html)
但是这样还是有问题,代码里我也写了accept()会阻塞线程,要在子线程里创建ServerSocket并且accept(),然后就是聊天室功能的具体逻辑了,我在代码里会注释,下面贴出完整代码
public class SocketTest {
public static void main(String[] args) {
new ServerListener().start();
// try {
// ServerSocket serverSocket= new ServerSocket(12346);
// Socket socket=serverSocket.accept();
// System.out.println("success");
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
//监听线程
public class ServerListener extends Thread {
public void run() {
try {
ServerSocket serverSocket=new ServerSocket(12340);
while(true){//循环监听连接
Socket socket=serverSocket.accept();
System.out.println("success");
//将socket传递给聊天线程
ChatSocket cs=new ChatSocket(socket);
cs.start();
ChatManager.getChatManager().add(cs);
}
} catch (Exception e) {
}
}
}
public class ChatSocket extends Thread {
Socket socket;
BufferedWriter bWriter;
BufferedReader br;
public ChatSocket(Socket socket) {
this.socket=socket;
}
public void out(String out) { //发送数据
try {
bWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bWriter.write(out+"\n");//必须要加\n
bWriter.flush();//这一句也要写,不然接收端收不到数据
System.out.println("out: "+out);
// bWriter.close();
} catch (Exception e) {
}
}
public void run() { //接收数据
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
String line=null;
//readLine是以\n为结束,所以接收端发送给服务器的消息要以\n结束
while ((line=br.readLine())!=null) {
ChatManager.getChatManager().publish(this, line);
System.out.println("input: "+line);
}
br.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//聊天管理类
public class ChatManager {
private ChatManager() {}
private static final ChatManager cm=new ChatManager();
public static ChatManager getChatManager() {
return cm;
}
Vector<ChatSocket> vector=new Vector<ChatSocket>();
//将ChatSocket添加进ChatManager
public void add(ChatSocket cs) {
vector.add(cs);
}
//向ChatManager里的ChatSocket发送消息
public void publish(ChatSocket cs,String out) {
for (int i = 0; i < vector.size(); i++) {
ChatSocket cSocket=vector.get(i);
if (!cs.equals(cSocket)) {//当前发送的socket就不用再接受消息了
cSocket.out(out);
}
}
}
}
上面就是socket的服务器端,下面讲android端,直接上代码
package com.example.administrator.serversockettest;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
private Button btn_connect, btn_send;
private EditText edIP, edContent;
private TextView tvContent;
private String IP;//本机IP 192.168.56.1
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_connect = (Button) findViewById(R.id.btn_connect);
btn_send = (Button) findViewById(R.id.btn_send);
edIP = (EditText) findViewById(R.id.edIP);
edContent = (EditText) findViewById(R.id.edContent);
tvContent = (TextView) findViewById(R.id.tvContent);
btn_connect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
IP = edIP.getText().toString();
connect();
}
});
btn_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
send();
}
});
}
private Socket socket = null;
private BufferedWriter writer = null;
private BufferedReader reader = null;
public void connect() { //连接线程
AsyncTask<Void, String, Void> read = new AsyncTask<Void, String, Void>() {
@Override
protected Void doInBackground(Void... voids) { //不能进行UI操作
try {
socket = new Socket(IP, 12340);
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
publishProgress("success");//调用publishProgress(),会进入onProgressUpdate()
} catch (IOException e) {
e.printStackTrace();
}
try {
String line;
//readLine是以\n为结束,所以服务器发送的消息要以\n结束
while ((line=reader.readLine())!=null) {
publishProgress(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(String... values) { //可以进行UI操作
tvContent.append("other: " + values[0] + "\n");
super.onProgressUpdate(values);
}
};
read.execute();
}
public void send() {
try {
tvContent.append("me: " + edContent.getText().toString() + "\n");
writer.write(edContent.getText().toString()+"\n");//以\n为结尾
writer.flush();//这句一定要加
edContent.setText("");
} catch (IOException e) {
e.printStackTrace();
}
}
}
xml文件
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.administrator.serversockettest.MainActivity">
<TableRow
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<EditText
android:id="@+id/edIP"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"/>
<Button
android:id="@+id/btn_connect"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="connect" />
</TableRow>
<TextView
android:id="@+id/tvContent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="20"
android:text="" />
<EditText
android:id="@+id/edContent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:hint="edit here"/>
<Button
android:id="@+id/btn_send"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:text="send" />
</TableLayout>
因为socket需要联网,所以还要在AndroidManifest里添加权限
<uses-permission android:name="android.permission.INTERNET"/>
注:输出流的发送的消息必须要以\n为结束,并且write()之后要调用flush(),否则接收端接收不到消息。
下面是android完整工程,java服务器我就不放了