服务器源码

import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;public class Server {    public static void main(String[] args){        //startServer=new startServer();        new startServer().start();//new 一个线程对象开始启动(由于startServer类继承了Thread)    }    public static ArrayList<UserThread> socketList=new ArrayList<UserThread>();//创建一个泛型是UserThread(UserThread是下面的一个类)的动态数组    public static startServer startServer;    static class startServer extends Thread{        public void run(){           try{               ServerSocket serverSocket = new ServerSocket(6666);               //创建端口值为:6666的ServerSocket对象               while(true){//死循环                   Socket socket = serverSocket.accept();//创建socket对象,用于接受客户端的请求                   System.out.println(""+socket);//用于显示客户端的IP地址,客户端的端口号,以及电脑的端口号                   UserThread userThread = new UserThread(socket);//通过下面定义的UserTread的有参构造,创建userThread对象                   Server.socketList.add(userThread);                   new Thread(userThread).start();//开启输入输出流线程               }           }catch(IOException e){               e.printStackTrace();           }        }    }    static class UserThread implements Runnable{        private Socket skt;        private DataOutputStream dos;        private DataInputStream dis;        public DataOutputStream getDos(){//返回输出流            return dos;        }        public void setDos(DataOutputStream dos){//给输出流传递参数            this.dos=dos;        }        public DataInputStream getDis(){//返回输入流            return dis;        }        public void setDis(DataInputStream dis){//给输入流传递参数            this.dis=dis;        }        public UserThread(Socket socket){//构造有参构造            skt=socket;        }        @Override        public void run(){            try{                dos= new DataOutputStream(skt.getOutputStream());//获取输出流(准备从服务器给其他的客户端发消息)                dis= new DataInputStream(skt.getInputStream());//接收客户端发过来的消息(输入流)                String recMsg ="";                while(true){//使服务器无限循环                    if(!"".equals(recMsg=dis.readUTF())){//读取输入流的消息,并把消息传到recMsg中                        System.out.println("收到一条消息"+ recMsg);//显示:收到一条消息+“传入的消息”                        for(UserThread s:socketList){//增强for循环                            if(s.equals(this)){                                continue;                            }                            try{                                s.getDos().writeUTF(recMsg);//将UTF-8的字符串写入字节流                            }catch(IOException e){                                socketList.remove(s);//将s从动态数组socketList中删除                                e.printStackTrace();                            }                        }                        recMsg="";//recMsg内容重新刷新                    }                }            }catch(IOException e){                e.printStackTrace();            }        }    }}

客户端源码

MainActivity

package com.example.my_chatroom;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.io.OutputStream;import java.net.Socket;public class MainActivity extends AppCompatActivity implements View.OnClickListener{    private OutputStream outputStream=null;    private Socket socket=null;    private String ip="192.168.1.66";    private Button btn_cnt;    private EditText et_ip;    private EditText et_name;    private EditText et_port;    private TextView myName;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        btn_cnt = (Button)findViewById(R.id.btn_cnt);        et_ip=findViewById(R.id.et_ip);        et_port=findViewById(R.id.et_port);        et_name=findViewById(R.id.et_name);        myName=findViewById(R.id.my_name);        btn_cnt.setOnClickListener(MainActivity.this);    }    public void onClick(View view){        String name = et_name.getText().toString();        if("".equals(name)){            Toast.makeText(this, "请输入用户名:", Toast.LENGTH_SHORT).show();        }else{            Intent intent = new Intent(MainActivity.this,ChatRoom.class);            intent.putExtra("name",et_name.getText().toString());            intent.putExtra("ip",et_ip.toString());            intent.putExtra("port",et_port.toString());            startActivity(intent);        }    }}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@drawable/picture">    <androidx.appcompat.widget.Toolbar        android:id="@+id/toolbar"        android:layout_width="match_parent"        android:layout_height="?attr/actionBarSize"        android:background="#3FA2F8">        <TextView            android:id="@+id/tv_room"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:text="登陆聊天室"            android:textColor="#F3F4F5"            android:textSize="20sp" />    </androidx.appcompat.widget.Toolbar>    <!--<View--> //注意大写,否则闪退    <!--android:id="@+id/ver_view"-->    <!--android:layout_toLeftOf="@+id/text_ip"-->    <!--android:layout_width="0dp"-->    <!--android:layout_height="match_parent"-->    <!--/>-->    <TextView        android:id="@+id/tv_name"        android:text="用户名"        android:textSize="20sp"        android:gravity="center"        android:layout_marginBottom="8dp"        android:layout_above="@+id/et_ip"        android:layout_marginLeft="45dp"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <EditText        android:id="@+id/et_name"        android:layout_toRightOf="@id/tv_name"        android:layout_above="@id/et_ip"        android:layout_width="150dp"        android:gravity="center"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/text_ip"        android:text="IP"        android:textSize="20sp"        android:layout_toLeftOf="@+id/et_ip"        android:layout_marginTop="5dp"        android:layout_width="60dp"        android:layout_height="wrap_content"        android:layout_below="@+id/tv_name"        />    <EditText        android:id="@+id/et_ip"        android:layout_width="150dp"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:text="192.168.1.66"        />    <TextView        android:id="@+id/tv_port"        android:layout_below="@+id/text_ip"        android:layout_marginLeft="45dp"        android:text="端口"        android:textSize="20sp"        android:layout_marginTop="20dp"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <EditText        android:id="@+id/et_port"        android:layout_width="150dp"        android:layout_height="wrap_content"        android:text="6666"        android:gravity="center"        android:layout_below="@+id/et_ip"        android:layout_marginLeft="20dp"        android:layout_toRightOf="@id/tv_port"        />    <Button        android:id="@+id/btn_cnt"        android:layout_width="100dp"        android:layout_height="wrap_content"        android:layout_below="@id/et_port"        android:layout_marginLeft="130dp"        android:layout_marginTop="30dp"        android:background="#07D0F3"        android:textColor="#ffffff"        android:text="连接" /></RelativeLayout>

ChatRoom

package com.example.my_chatroom;import androidx.annotation.NonNull;import androidx.appcompat.app.AlertDialog;import androidx.appcompat.app.AppCompatActivity;import androidx.recyclerview.widget.LinearLayoutManager;import androidx.recyclerview.widget.RecyclerView;import android.annotation.SuppressLint;import android.content.DialogInterface;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.text.TextUtils;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.io.DataInput;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;public class ChatRoom extends AppCompatActivity implements View.OnClickListener{    private List<Msg> msgList = new ArrayList<>();    private EditText inputText;    private Button send;    private Button back;    private RecyclerView msgRecyclerView;    private MsgAdapter adapter;    private Socket socketSend;    private String ip="192.168.1.66";    private String port="6666";    DataInputStream dis;    DataOutputStream dos;    boolean isRunning = false;    private TextView myName;    private String recMsg;    private boolean isSend=false;    private String name;    private Handler handler = new Handler(Looper.myLooper()){//获取当前进程的Looper对象传给handler        @Override        public void handleMessage(@NonNull Message msg){//?            if(!recMsg.isEmpty()){                addNewMessage(recMsg,Msg.TYPE_RECEIVED);//添加新数据            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_chat_room);        Intent intent =getIntent();        name=intent.getStringExtra("name");        inputText = findViewById(R.id.input_text);        send=findViewById(R.id.send);        send.setOnClickListener(this);        back = findViewById(R.id.back);        back.setOnClickListener(new View.OnClickListener(){            @Override            public void onClick(View view){                AlertDialog.Builder dialog= new AlertDialog.Builder(ChatRoom.this);                dialog.setTitle("退出");                dialog.setMessage("退出登录?");                dialog.setCancelable(false);                dialog.setPositiveButton("是", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialogInterface, int i) {                        finish();//finish()是在程序执行的过程中使用它来将对象销毁,finish()方法用于结束一个Activity的生命周期                    }                });                dialog.setNegativeButton("否", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialogInterface, int i) {                    }                });                dialog.show();//让返回键开始启动            }        });        runOnUiThread(new Runnable() {            @Override            public void run() {                LinearLayoutManager layoutManager = new LinearLayoutManager(ChatRoom.this);                msgRecyclerView= findViewById(R.id.msg_recycler_view);                msgRecyclerView.setLayoutManager(layoutManager);                adapter = new MsgAdapter(msgList);                msgRecyclerView.setAdapter(adapter);            }        });        new Thread(new Runnable(){            @Override            public void run(){                try{                    if((socketSend = new Socket(ip,Integer.parseInt(port)))==null){                        Log.d("ttw","发送了一条消息1");                    }                    else{                        isRunning = true;                        Log.d("ttw","发送了一条消息2");                        dis = new DataInputStream(socketSend.getInputStream());                        dos = new DataOutputStream(socketSend.getOutputStream());                        new Thread(new receive(),"接收线程").start();                        new Thread(new Send(),"发送线程").start();                    }                }catch(Exception e){                    isRunning = false;                    e.printStackTrace();                    Looper.prepare();                    Toast.makeText(ChatRoom.this, "连接服务器失败!!!", Toast.LENGTH_SHORT).show();                    Looper.loop();                    try{                        socketSend.close();                    }catch(IOException e1){                        e1.printStackTrace();                    }                    finish();                }            }        }).start();    }    public void addNewMessage(String msg,int type){        Msg message = new Msg(msg,type);        msgList.add(message);        adapter.notifyItemInserted(msgList.size()-1);        msgRecyclerView.scrollToPosition(msgList.size()-1);    }    class receive implements Runnable{        public void run(){            recMsg = "";            while(isRunning){                try{                    recMsg = dis.readUTF();                    Log.d("ttw","收到了一条消息"+"recMsg: "+ recMsg);                }catch(Exception e){                    e.printStackTrace();                }                if(!TextUtils.isEmpty(recMsg)){                    Log.d("ttw","inputStream:"+dis);                    Message message = new Message();                    message.obj=recMsg;                    handler.sendMessage(message);                }            }        }    }    @Override    public void onClick(View view){        String content = inputText.getText().toString();        @SuppressLint("SimpleDateFormat")        String date = new SimpleDateFormat("hh:mm:ss").format(new Date());        StringBuilder sb = new StringBuilder();        sb.append(content).append("\n\n"+date);        content = sb.toString();        if(!"".equals(content)){            Msg msg = new Msg(content,Msg.TYPE_SENT);            msgList.add(msg);            adapter.notifyItemInserted(msgList.size()-1);            msgRecyclerView.scrollToPosition(msgList.size()-1);            isSend = true;        }        sb.delete(0,sb.length());    }    class Send implements Runnable{        @Override        public void run(){            while(isRunning){                String content = inputText.getText().toString();                Log.d("ttw","发了一条消息");                if(!"".equals(content)&&isSend){                    @SuppressLint("SimpleDateFormat")                    String date = new SimpleDateFormat("hh:mm:ss").format(new Date());                    StringBuilder sb = new StringBuilder();                    sb.append(content).append("\n\n来自:").append(name).append("\n"+date);                    content = sb.toString();                    try{                        dos.writeUTF(content);                        sb.delete(0,sb.length());                        Log.d("ttw","发送了一条消息");                    }catch(IOException e){                        e.printStackTrace();                    }                    isSend = false;                    inputText.setText("");                }            }        }    }}

activity_chat_room.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:orientation="vertical"    android:background="#d8e0e8"    android:layout_width="match_parent"    android:layout_height="match_parent">    <androidx.appcompat.widget.Toolbar        android:id="@+id/toolbar"        android:layout_width="match_parent"        android:layout_height="?attr/actionBarSize"        android:background="#187C8F">        <Button            android:id="@+id/back"            android:layout_width="50dp"            android:layout_height="wrap_content"            android:background="@drawable/back" />        <TextView            android:id="@+id/text_room"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:text="聊天室"            android:textColor="#F3F4F5"            android:textSize="20sp" />    </androidx.appcompat.widget.Toolbar>    <androidx.recyclerview.widget.RecyclerView        android:id="@+id/msg_recycler_view"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:background="@drawable/background" />    <LinearLayout        android:orientation="horizontal"        android:layout_width="match_parent"        android:layout_height="wrap_content">        <EditText            android:id="@+id/input_text"            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:background="#ffffff"            />        <Button            android:id="@+id/send"            android:layout_width="wrap_content"            android:layout_height="50dp"            android:background="#07D0F3"            android:text="发送"            android:textColor="#ffffff" />    </LinearLayout></LinearLayout>

msg_item.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:padding="10dp"    >    <LinearLayout        android:id="@+id/left_layout"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="left"        >        <ImageView            android:id="@+id/iv_head_others"            android:background="@drawable/headofothers"            android:layout_marginTop="20dp"            android:layout_width="60dp"            android:layout_height="60dp" />        <LinearLayout            android:orientation="vertical"            android:layout_width="wrap_content"            android:layout_height="wrap_content">            <TextView                android:id="@+id/others_name"                android:layout_gravity="left"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />            <TextView                android:id="@+id/left_msg"                android:textStyle="bold"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_marginTop="5dp"                android:layout_marginBottom="5dp"                android:background="@drawable/qipao_2"                android:layout_gravity="center"                android:textColor="#B955B9" />        </LinearLayout>    </LinearLayout>    <LinearLayout        android:id="@+id/right_layout"        android:layout_gravity="right"        android:layout_width="wrap_content"        android:layout_height="wrap_content">        <LinearLayout            android:orientation="vertical"            android:layout_width="wrap_content"            android:layout_height="wrap_content">            <TextView                android:id="@+id/my_name"                android:layout_gravity="right"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />            <TextView                android:id="@+id/right_msg"                android:textStyle="bold"                android:layout_gravity="center"                android:background="@drawable/qipao_1"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />        </LinearLayout>        <ImageView            android:id="@+id/iv_head_my"            android:background="@drawable/headofmy"            android:layout_marginTop="20dp"            android:layout_width="60dp"            android:layout_height="60dp" />    </LinearLayout></LinearLayout>

Msg

package com.example.my_chatroom;public class Msg {    public static final int TYPE_RECEIVED=0;    public static final int TYPE_SENT =1;    public String getContent(){        return content;    }    public int getType(){        return type;    }    private String content;    private int type;    public Msg(String content,int type){        this.content=content;        this.type=type;    }}

MsgAdapter

package com.example.my_chatroom;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.TextView;import androidx.annotation.NonNull;import androidx.recyclerview.widget.RecyclerView;import java.util.List;public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {    private List<Msg> mMsgList;    @NonNull    @Override    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,int viewType){        //ViewHolder通常出现在适配器里,为的是listview滚动的时候快速设置值,而不必每次都重新创建很多对象,从而提升性能。        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);        //LayoutInflat.from()从一个Context中,获得一个布局填充器,这样你就可以使用这个填充器来把xml布局文件转为View对象了。        //LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);这样的方法来加载布局msg_item.xml        return new ViewHolder(view);    }    @Override    public void onBindViewHolder(@NonNull ViewHolder holder,int position){        Msg msg =mMsgList.get(position);        if(msg.getType()==Msg.TYPE_RECEIVED){            holder.leftLayout.setVisibility(View.VISIBLE);            holder.rightLayout.setVisibility(View.GONE);            holder.leftMsg.setText(msg.getContent());        }else if(msg.getType()==Msg.TYPE_SENT){            holder.leftLayout.setVisibility(View.GONE);            holder.rightLayout.setVisibility(View.VISIBLE);            holder.rightMsg.setText(msg.getContent());        }    }    @Override    public int getItemCount(){        return mMsgList.size();    }    static class ViewHolder extends RecyclerView.ViewHolder{        LinearLayout leftLayout;        LinearLayout rightLayout;        TextView leftMsg;        TextView rightMsg;        public ViewHolder(@NonNull View view){            super(view);            leftLayout = view.findViewById(R.id.left_layout);            rightLayout = view.findViewById(R.id.right_layout);            leftMsg = view.findViewById(R.id.left_msg);            rightMsg = view.findViewById(R.id.right_msg);        }    }    public MsgAdapter (List<Msg> msgList){        mMsgList = msgList;    }}

shape.xml

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <solid        android:color="#07D0F3"/></selector>

previous.xml

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <solid        android:color="#0fffff"/></selector>

click.xml

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <corners        android:radius="20dp"/>    <item android:drawable="@drawable/shape"        android:state_enabled="true"        android:state_pressed="true"/>    <item android:drawable="@drawable/previous"        android:state_enabled="true"        android:state_pressed="false"/></selector>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.my_chatroom">    <uses-permission android:name="android.permission.INTERNET"/>    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="聊天室"        android:roundIcon="@mipmap/ic_launcher_round"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".ChatRoom"/>        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <action android:name="android.intent.action.VIEW" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

另外,在说明一点,如果需要修改App图标的话

路径

修改位置

其中theme是我选中的一张图片

更多相关文章

  1. 类和 Json对象
  2. Android(安卓)蓝牙(BLE)连接,发送,接收消息
  3. android 单选,复选按钮,以及toast
  4. Android库. 1 UDP客户端
  5. java 后端实现WebSocket学习篇和客户端Android(安卓)通信
  6. [Mobile Web]Web中如何分辨移动设备?(iPad、iPhone、Android)
  7. Android作为客户端,采用Netty与服务器通信
  8. Android(安卓)MQTT
  9. Android(安卓)4.0 gallery2 生成video thumbnail的过程

随机推荐

  1. 下拉刷新系列二:SmartRefreshLayout 使用
  2. Annotation Processor在Android下的应用
  3. Android网络编程之——Android登录系统模
  4. Android媒体扫描代码分析
  5. 什么是Anddroid ANR
  6. [置顶] 定义一个ImageVIew出现警告的去除
  7. 用SQLiteOpenHelper实现操作SQLite
  8. AdapterViewFlipper实现翻滚广告效果
  9. andorid跳过系统API获取以太网IP,网关,DNS,M
  10. 引入第三方库ic_launcher冲突