相关阅读:Java Socket聊天室编程(二)之利用socket实现单聊聊天室
网上已经有很多利用socket实现聊天的例子了,但是我看过很多,多多少有一些问题存在。
这里我将实现一个比较完整的聊天例子,并解释其中的逻辑。
由于socket这一块比较大,所以我将分出几篇来写一个比较完整的socket例子。
这里我们先来实现一个最简单的,服务器与客户端通讯,实现消息推送的功能。
目的:服务器与客户端建立连接,客户端可以向服务器发送消息,服务器可以向客户端推送消息。
1,使用java建立socket聊天服务器
1,SocketUrls 确定ip地址和端口号
public class SocketUrls{// ip地址public final static String IP = "192.168.1.110";// 端口号public final static int PORT = 8888;}
2,Main 程序的入口
public class Main {public static void main(String[] args) throws Exception {new ChatServer().initServer();}}
3,Bean 实体类
用户信息 UserInfoBean
public class Main {public static void main(String[] args) throws Exception {new ChatServer().initServer();}}
聊天信息 MessageBean
public class MessageBean extends UserInfoBean {private long messageId;// 消息idprivate long groupId;// 群idprivate boolean isGoup;// 是否是群消息private int chatType;// 消息类型;1,文本;2,图片;3,小视频;4,文件;5,地理位置;6,语音;7,视频通话private String content;// 文本消息内容private String errorMsg;// 错误信息private int errorCode;// 错误代码//省略get/set方法}
4,ChatServer 聊天服务,最主要的程序
public class ChatServer {// socket服务private static ServerSocket server;public Gson gson = new Gson();/*** 初始化socket服务*/public void initServer() {try {// 创建一个ServerSocket在端口8080监听客户请求server = new ServerSocket(SocketUrls.PORT);createMessage();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 创建消息管理,一直接收消息*/private void createMessage() {try {System.out.println("等待用户接入 : ");// 使用accept()阻塞等待客户请求Socket socket = server.accept();System.out.println("用户接入 : " + socket.getPort());// 开启一个子线程来等待另外的socket加入new Thread(new Runnable() {public void run() {createMessage();}}).start();// 向客户端发送信息OutputStream output = socket.getOutputStream();// 从客户端获取信息BufferedReader bff = new BufferedReader(new InputStreamReader(socket.getInputStream()));// Scanner scanner = new Scanner(socket.getInputStream());new Thread(new Runnable() {public void run() {try {String buffer;while (true) {// 从控制台输入BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));buffer = strin.readLine();// 因为readLine以换行符为结束点所以,结尾加入换行buffer += "/n";output.write(buffer.getBytes("utf-8"));// 发送数据output.flush();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}).start();// 读取发来服务器信息String line = null;// 循环一直接收当前socket发来的消息while (true) {Thread.sleep(500);// System.out.println("内容 : " + bff.readLine());// 获取客户端的信息while ((line = bff.readLine()) != null) {MessageBean messageBean = gson.fromJson(line, MessageBean.class);System.out.println("用户 : " + messageBean.getUserName());System.out.println("内容 : " + messageBean.getContent());}}// server.close();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("错误 : " + e.getMessage());}}}
2,Android 端作为移动端连接服务器
1,appliaction 实例化一个全局的聊天服务
public class ChatAppliaction extends Application {public static ChatServer chatServer;public static UserInfoBean userInfoBean;@Overridepublic void onCreate() {super.onCreate();}}
2,ip地址和端口号和服务器保持一致
3,聊天实力类同服务器端一样
4,xml布局。登陆,聊天
1,登录
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:id="@+id/chat_name_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="用户名"android:text="admin"/><EditTextandroid:id="@+id/chat_pwd_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="密码"android:text="123123123a"android:inputType="numberPassword" /><Buttonandroid:id="@+id/chat_login_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="登录" /></LinearLayout>
2,聊天
<?xml version="1.0" encoding="utf-8"?><LinearLayout 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"android:orientation="vertical"tools:context=".activity.MainActivity"><ScrollViewandroid:id="@+id/scrollView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="0.9"><LinearLayoutandroid:id="@+id/chat_ly"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"></LinearLayout></ScrollView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><EditTextandroid:id="@+id/chat_et"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="0.8" /><Buttonandroid:id="@+id/send_btn"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="0.2"android:text="发送" /></LinearLayout></LinearLayout>
5,LoginActivity 登陆
public class LoginActivity extends AppCompatActivity {private EditText chat_name_text, chat_pwd_text;private Button chat_login_btn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);chat_name_text = (EditText) findViewById(R.id.chat_name_text);chat_pwd_text = (EditText) findViewById(R.id.chat_pwd_text);chat_login_btn = (Button) findViewById(R.id.chat_login_btn);chat_login_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (getLogin(chat_name_text.getText().toString().trim(), chat_pwd_text.getText().toString().trim())) {getChatServer();Intent intent = new Intent(LoginActivity.this, MainActivity.class);startActivity(intent);finish();}}});}private boolean getLogin(String name, String pwd) {if (TextUtils.isEmpty(name) || TextUtils.isEmpty(pwd)) return false;if (name.equals("admin") && pwd.equals("123123123a")) return true;return false;}private void getChatServer() {ChatAppliaction.chatServer = new ChatServer();}}
6,MainActivity 聊天
public class MainActivity extends AppCompatActivity {private LinearLayout chat_ly;private TextView left_text, right_view;private EditText chat_et;private Button send_btn;private ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);chat_ly = (LinearLayout) findViewById(R.id.chat_ly);chat_et = (EditText) findViewById(R.id.chat_et);send_btn = (Button) findViewById(R.id.send_btn);send_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {ChatAppliaction.chatServer.sendMessage(chat_et.getText().toString().trim());chat_ly.addView(initRightView(chat_et.getText().toString().trim()));}});//添加消息接收队列ChatAppliaction.chatServer.setChatHandler(new Handler() {@Overridepublic void handleMessage(Message msg) {if (msg.what == 1) {//发送回来消息后,更新uichat_ly.addView(initLeftView(msg.obj.toString()));}}});}/**靠右的消息* @param messageContent* @return*/private View initRightView(String messageContent) {right_view = new TextView(this);right_view.setLayoutParams(layoutParams);right_view.setGravity(View.FOCUS_RIGHT);right_view.setText(messageContent);return right_view;}/**靠左的消息* @param messageContent* @return*/private View initLeftView(String messageContent) {left_text = new TextView(this);left_text.setLayoutParams(layoutParams);left_text.setGravity(View.FOCUS_LEFT);left_text.setText(messageContent);return left_text;}}
7,ChatServer 聊天逻辑,最主要的
public class ChatServer {private Socket socket;private Handler handler;private MessageBean messageBean;private Gson gson = new Gson();// 由Socket对象得到输出流,并构造PrintWriter对象PrintWriter printWriter;InputStream input;OutputStream output;DataOutputStream dataOutputStream;public ChatServer() {initMessage();initChatServer();}/*** 消息队列,用于传递消息** @param handler*/public void setChatHandler(Handler handler) {this.handler = handler;}private void initChatServer() {//开个线程接收消息receiveMessage();}/*** 初始化用户信息*/private void initMessage() {messageBean = new MessageBean();messageBean.setUserId(1);messageBean.setMessageId(1);messageBean.setChatType(1);messageBean.setUserName("admin");ChatAppliaction.userInfoBean = messageBean;}/*** 发送消息** @param contentMsg*/public void sendMessage(String contentMsg) {try {if (socket == null) {Message message = handler.obtainMessage();message.what = 1;message.obj = "服务器已经关闭";handler.sendMessage(message);return;}byte[] str = contentMsg.getBytes("utf-8");//将内容转utf-8String aaa = new String(str);messageBean.setContent(aaa);String messageJson = gson.toJson(messageBean);/*** 因为服务器那边的readLine()为阻塞读取* 如果它读取不到换行符或者输出流结束就会一直阻塞在那里* 所以在json消息最后加上换行符,用于告诉服务器,消息已经发送完毕了* */messageJson += "/n";output.write(messageJson.getBytes("utf-8"));// 换行打印output.flush(); // 刷新输出流,使Server马上收到该字符串} catch (Exception e) {e.printStackTrace();Log.e("test", "错误:" + e.toString());}}/*** 接收消息,在子线程中*/private void receiveMessage() {new Thread(new Runnable() {@Overridepublic void run() {try {// 向本机的8080端口发出客户请求socket = new Socket(SocketUrls.IP, SocketUrls.PORT);// 由Socket对象得到输入流,并构造相应的BufferedReader对象printWriter = new PrintWriter(socket.getOutputStream());input = socket.getInputStream();output = socket.getOutputStream();dataOutputStream = new DataOutputStream(socket.getOutputStream());// 从客户端获取信息BufferedReader bff = new BufferedReader(new InputStreamReader(input));// 读取发来服务器信息String line;while (true) {Thread.sleep(500);// 获取客户端的信息while ((line = bff.readLine()) != null) {Log.i("socket", "内容 : " + line);Message message = handler.obtainMessage();message.obj = line;message.what = 1;handler.sendMessage(message);}if (socket == null)break;}output.close();//关闭Socket输出流input.close();//关闭Socket输入流socket.close();//关闭Socket} catch (Exception e) {e.printStackTrace();Log.e("test", "错误:" + e.toString());}}}).start();}}
写到这里,已经完成了所有的代码。
这个demo可以实现手机端向服务器发送消息,服务器向手机端发送消息。
这个demo可以算是推送功能,不过真正的推送没有这么简单。作为一个socket的入门了解,可以从中看到socket编程的思想。
以上所述是小编给大家介绍的Java Socket聊天室编程(一)之利用socket实现聊天之消息推送,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!
新闻热点
疑难解答