android网络编程--Socket通信(03)点对点Android聊天室实现(带服务器。。。

更新时间:2023-04-21 22:23:26 阅读: 评论:0


2023年4月21日发(作者:有效的学习方法)

android⽹络编程--Socket通信(03)点对点Android聊天室实

现(带服务器。。。

1-简介:

概念:在⽹络上的两个程序通过⼀个双向的通信连接实现数据的交换,这个双向链路的⼀端称为⼀个socket。

组成:由⼀个IP地址和⼀个端⼝号唯⼀确定,是TCP/IP 协议的⼀个⼗分流⾏的编程界⾯。

应⽤:socket编程⽐基于URL的HTTP⽹络编程提供了更⾼的传输效率、更强⼤的功能和更灵活的控制,但却复杂⼀些。

地位:socket已经是java中层次最低的⽹络编程接⼝,在java中直接操作协议中更低的层次,需要使⽤java本地⽅法调⽤(JNI)。

基础:Server端监听某个端⼝是否有连接请求,Client端向Server端发出连接请求,Server端向Client端发回Accept消息,⼀个连接就建

⽴起来了;

Server和Client端都可以⽤Send和Write等⽅法,与对⽅通信,Java在包中提供了两个类Socket和ServerSocket。

⽬前⽹上的资源⼤都⽆法实现点对点通信,要么⽤服务器⼴播,本实例将实现socket 指定的点点通信。

2-功能简介:

界⾯设计有点挫,重点在于功能,这是安卓客户端, 上⾯的 spinner下拉列表⽤来选择在线⽤户,

中间的TextView⽤于显⽰接收到的信息,(这⾥设计略简单,只做DEMO参考级别),

最下⾯输⼊聊天内容,发送按钮进⾏点对点通信。

3-服务器编程:

S1.新建⼀个java⼯程充当java 服务器,命名为ChatServer

S2 编写服务器程序:

服务器有三个联⽹类组成:

Thread

服务线程,启动服务器时启动,开启服务ServerSocket⽤以监听端⼝收到的客户端信息。

package ;

import ption;

import Socket;

import ;

import ist;

import p;

import ;

public class ServerThread implements Runnable {

// ServerSocket 类对象

private ServerSocket rverSocket = null;

// 服务醋乳香的功效与作用点 器端⼝设置

private static final int PORT = 8888;

// 存储接收到客户端的消息

public List messagelt = null;

// 服务器启动标志位

private boolean isStart = true;

// 存储客户端socket

// 存储客户端socket

public HashMap clientsMap = null;

/**

* 构造函数

*/

public ServerThread(){

// 初始化 message 存储list

messagelt = new ArrayList();

// 初始化客户端socket

clientsMap = new HashMap();

try {

// 开启服务器socket

rverSocket = new ServerSocket(PORT);

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

// 启动消息处理线程

new Thread(new MessageHandlerThread(this)).start();

}

/**

* ⼀旦有客户端连⼊,就启动客户端处理线程,并加⼊服务器客户端HashMap

*/

@Override

public void run() {

// TODO Auto-generated method stub

while(isStart){

try {

// 获取⼀个连接客户端

Socket socket = ();

n("连⼊⼀个客户端:" + tAddress().getHostAddress());

// 创建clientHandler线程

ClientHandlerThread clientRunnable = new ClientHandlerThread(s溺水作文 ocket, this);

Thread clientThread = new Thread(clientRunnable);

();

// 将成功获取到的客户端保存起来

if(socket != null){

synchronized(clientsMap){

(tAddress().getHostAddress(), clientRunnable);

}

}

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

}

}

/**

* 关闭 ServerSocket

*/

public void finalize(){

// 关闭 ServerSocket

try {

();

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

tackTrace();

}

rverSocket = null;

}

}

class Message{

public String IP;

public String info;

public Message(String iP, String info) {

super();

IP = iP;

= info;

}

}

HandlerThread

客户端处理线程,当有⼀个客户端连⼊服务器时,启动⼀个线程接收客户端信息。

package ;

import putStream;

import tputStream;

import ption;

import ;

public class ClientHandlerThread implements Runnable {

// 客户端socket

public Socket clientSocket = null;

// socket 的输⼊,输出流

private DataInputStream in = null;

public DataOutputStream out = null;

// 服务器线程ServerThread

private ServerThread rverThread = null;

/**

* 构造函数

* @param socket

* @param rverThread

*/

public ClientHandlerThread(Socket socket, ServerThread rverThread){

Thread = rverThread;

Socket = socket;

// 获取对服务器操作的输⼊输出流

try {

in = new DataInputStream(utStream());

out = new DataOutputStream(putStream());

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

}

/**

* 监听对应的客户端是否有消息发送

*/

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

try {

String iP = F();

String info = F();

Message message = new Message(iP, info);

// 打印接收信息

n("[" + tAddress().getHostAddress() + "] -> [" + + "]:" + );

// 将客户端发送的信息存储到 Message LIST

synchronized (elt) {

(message);

}

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

break;

}

}

}

}

eHandlerThread

package ;

import ption;

import or;

public class MessageHandlerThread implements Runnable{

// 客户端线程

private ClientHandlerThread clientThread = null;

暖性食物 // 服务器线程

private ServerThread rverThread = null;

// 处理的消息

private Message message = null;

/**

* 构造函数

* @param rverThread

*/

public MessageHandlerThread(ServerThread rverThread){

Thread = rverThread;

}

@Override

public void ru熹妃传厨房攻略 n() {

// TODO Auto-generated method stub

while(true){

// 线程休眠100ms

try {

(100);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

tackTrace();

}

// 获取要处理的信息

synchronized (elt) {

// 判断是否有未发送的信息

if(y()){

continue;

}

message = (0);

}

// 处理信息

synchronized (sMap) {

if(("10.0.2.2")) = "127.0.0.1";

// 获取要发送的客户端

clientThread = ();

try {

// 获取所有⽤户

if(("{GETALL}")){

String info = "";

Iterator iterator = ().iterator();

while(t()) {

info += (()).tAddress().getHostAddress();

info += ";";

}

= info;

}

// 发送数据

TF();

TF();

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

// rver LIST中删除掉已经处理的消息

(message);

}

}

}

}

4-安卓客户端编程

S1 Socket通信模块编程

该设计按照单例模式设计,即全局不构造对象,类变量只有⼀个实例。

这样的设计提⾼了socket利⽤率,节省了代码量。

package ;

import putStream;

import tputStream;

import ption;

import ;

import nHostException;

public class ChatClient {

private static Socket clientSocket = null;

private static DataInputStream in = null;

private static DataOutputStream out = null;

private static String IP = "10.0.2.2";

private static int PORT = 8888;

public static Socket getSocket(){

if(clientSocket == null){

try {

clientSocket = new Socket(IP, PORT);

} catch (UnknownHostException e) {

// TODO Auto-generated catch block

tackTrace();

} catch (IOEsuv那个好 xception e) {

// TODO Auto-generated catch block

tackTrace();

}

}

return clientSocket;

}

public static DataInputStream getDataInputStream(){

if(in == null){

getSocket();

try {

in = new DataInputStream(utStream());

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

}

return in;

}

public static DataOutputStream getDataOutputStream(){

if(out == null){

getSocket();

try {

out = new DataOutputStream(putStream());

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

}

return out;

}

}

S2 安卓端界⾯简单设计

tivity

Spinner控件的设计,⽤于选择在线⽤户;

TextView控件为了显⽰聊天记录信息;

EditView控件为了获取⽤户输⼊的数据信息;

Button控件为了发送⽤户信息;

package tdemo;

import ption;

import ty;

import ;

import r;

import e;

import ;

import kListener;

import rView;

import SelectedListener;

import dapter;

import ;

import xt;

import r;

import ew;

import ient;

public class MainActivity extends Activity implements OnClickListener, Runnable {

private Spinner urList = null;

private Button ndBtn = null;

private EditText infoEdit = null;

private甘之如饴造句 String message = null;

private String[] mUrs = null;

private TextView infoArea = null;

@Override

protected void onCreate(Bundle savedInstanceState) {

te(savedInstanceState);

tContentView(ty_main);

urList = (Spinner) ewById(st);

infoEdit = (EditText) findViewById(it);

ndBtn = (Button) findViewById(n);

infoArea = (TextView) findViewById(ea);

lickListener(this);

try {

//获得本机IP

InetAddress addr = alHost();

String ip = tAddress().toString();

aOutputStream().writeUTF(ip);

aOutputStream().writeUTF("{GETALL}");

String respon = aInputStream().readUTF();

mUrs = (";");

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

ArrayAdapter adapter = new ArrayAdapter(this,

_spinner_item, mUrs);

pDownViewResource(_spinner_dropdown_item);

pter(adapter);

new Thread(this).start();

}

@Override

public void onClick(View v) {

// TODO Auto-ge老爸生日祝福语 nerated method stub

switch(()){

ca n:

String ip = ectedItem().toString();

String info = t().toString();

try {

aOutputStream().writeUTF(ip);

aOutputStream().writ小说里的经典语录 eUTF(info);

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

break;

}

}

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

try {

message = aInputStream().readUTF();

message += "n";

ssage(Message());

} catch (IOException e) {

// TODO Auto-generated catch block

tackTrace();

}

}

}

private Handler mHandler = new Handler(){

/**

* 获取⼀个消息,刷新对话框

*/

public void handleMessage(Message msg){

(message);

Message(msg);

}

};

}

ty_

xmlns:tools="/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context=".MainActivity" >

android:id="@+id/urList"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

android:id="@+id/chatArea"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_weight="1.05"/>

android:id="@+id/infoEdit"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:ems="10" >

android:id="@+id/ndBtn"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:text="发送" />

S3.增加联⽹权限

5-运⾏效果

先启动服务器,然后启动客户端,选择聊天对象,即可实现点对点通信。

PS.⼏点遗憾:

r控件没有获取到点击事件,导致⽆法更新在线⼈信息,但这个与socket通信⽆关,后期将会把更新版本补充上。

2.由于开启虚拟机测试,不能实现现场点对点通信(虚拟机IP相同导致的),真机测试,效果会更好。

3.之前想⽤传统的ObjectInputStream,然后将信息交换定义为⼀系列的Message类,但考虑到服务器不知⽤于java通信,如果这样写可

能会让跨语⾔通信失败。

本实例精华重在⼀个HashMap映射思想和,MessageHandlerThread消息处理线程的设计,⽤以实现的点点通信机制。

附上源码:

没有积分的请留⾔邮箱~


本文发布于:2023-04-21 22:23:26,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/841735.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:点对点通信
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图