Android中基于socket的网络通信

本文介绍编写一个使用Socket完成Android客户端与服务器端通信的简单Demo

详细代码地址:github.com/Baolvlv/LearnAndroid/tree/master/MySocketClient

(1)Socket介绍

Socket,又称套接字,应用通过socket向网络发出请求或应答网络请求

在java中,Socket与ServerSocket位于java.net包中。ServerSocket位于服务器端,Socket位于客户端。连接成功时,两端都产生一个Socket实例,通过操作这个实例完成会话。两端的实例平等,没有差别,通过Socket与其子类完成所有操作。

(2)Sokcet链接建立过程

1.服务器监听    2.客户端发出请求    3.建立链接    4.通信

(3)Socket的特点

Socket基于Tcp链接,数据传输有保障

Socket适用于建立长时间链接

Socket编程通常应用于即时通信

Eclipse中新建java工程,包,类。

创建ServerSocket对象,自定义通信端口号(1-65535)65535最大的16位为二进制数。

// 构造函数参数为SerSocket侦听的端口,取值1-65535

//随意取值,使用较大的端口,与预留端口区分

try{//创建serverSocket对象

ServerSocket

serverSocket=newServerSocket(12345);

调用serverSocket.accept方法,侦听客户端的请求,创建socket。此方法在客户端请求之前会导致线程一直为阻塞状态。当accept方法执行,socket被赋值,则说明链接建立。

//侦听客户端的请求,会阻塞当前线程  block

//accept方法执行,socket被赋值,则说明链接建立

Socket

socket=serverSocket.accept();

建立连接后,服务器端弹出对话框,使用java swing

//建立链接后执行,弹出对话框,第一个参数为父级容器

JOptionPane.showMessageDialog(

null,"有客户端链接到了本机的12345端口");

此时运行程序,程序会一直运行,直到客户端发出请求,建立连接后弹出对话框结束

2.使用ServerSocket建立聊天服务器

会阻塞主线程的程序应该单独放在一个线程中

创建ChatSocket类继承自Thread,用于执行客户端连接后的输出操作

//声明Socket对象

Socket

socket

;

//构造函数接收外部传入的SocketpublicChatSocket(Sockets

){

this.socket=s

;

}

创建输出函数,使用输出流进行输出

publicvoidout(Stringout) {

socket.getOutputStream().write(out.getBytes("UTF-8"));

复写Thread类的run方法,执行输出操作,每隔1秒输出一次

publicvoidrun() {intcount

= 0;

//不断执行输出操作while(true

){

out(

"loop"+count

);

count

++;

try

{

//每隔1秒输出一次

sleep(1000);

}

catch(InterruptedExceptione

) {

//TODOAuto-generated catch blocke

.printStackTrace();

}

自定义ServerListener类继承自Thread,用于执行侦听客户端的请求,创建socket,为每个客户端进行输出操作

创建ServerSocket,继承自Thread类

publicclassServerListenerextendsThread {

复写run方法,规定端口,创建ServerSocket对象

ServerSocketserverSocket=newServerSocket(12345);

不断循环,每当客户端发出请求,serverSocket.accept()方法执行一次,创建一个新Socket对象,将创建的socket传入,启动输出线程

while(true){

Socketsocket=serverSocket.accept();

newChatSocket(socket).start();

}

Telnet是进行远程登录的标准协议和主要方式它为用户提供了在本地计算机上完成远程主机工作的能力。可以用telnet命令来测试端口号是否正常打开还是关闭状态。

测试命令:控制台输入  telnet localhost 12345

会在控制台不断输出请求结果

添加一个客户端发出消息,其他客户端接收消息的功能

创建ChatManager类,用于管理每个客户端对象创建的用于聊天的ChatSocket线程对象

由于每个聊天服务器只能拥有一个ChatManger类,所以使用单例模式

创建private的构造方法和private对象,public static返回对象的方法

//私有化构造方法private

ChatManager() {}

//为当前的类创建唯一的实例privatestaticfinalChatManagercm=new

ChatManager();

//创建返回唯一实例的public static方法publicstatic

ChatManager getChatManager() {

returncm

;

}

创建Vector,范型为ChatSocket,用于管理客户端的聊天线程

//创建Vector,管理每一个客户端创建的ServerSocket线程对象

Vector

vector=newVector<>();

创建向Vector中添加元素的方法

//Vector的添加方法publicvoidadd(ChatSocketcs

) {

vector.add(cs);

创建发布消息的方法,参数为发布消息的chatSocket和发布的消息

遍历Vector的中的所有元素,对不是发布消息的其他ChatSocket执行out方法

在发布消息的ChatSocket内部调用此方法

//其中任意一个线程可以调用publish方法向其他的客户端发布信息publicvoidpublish(ChatSocketcs,Stringout

) {

//遍历vector中的元素for(inti= 0;i

++){

//创建方法内部的本地对象

ChatSocket

cSocket=vector.get(i

);

//判断,不向自身发布消息if(!cSocket.equals(cs

)){

//调用输出方法,输出需要发送的信息cSocket.out(out

);

}

当客户端连接时,创建socket,创建ChatSocket,将创建的ChatSocket添加到ChatManager中

Socketsocket=serverSocket.accept();

ChatSocketchatSocket=newChatSocket(socket);chatSocket.start();//当ChatSocket线程创建时,将它添加到ChatManager中

ChatManager.getChatManager().add(

chatSocket);

当前客户端获取输出流进行输出

//向客户端发送数据

socket.getOutputStream().write(outline.getBytes("UTF-8"));

在ChatSocket中,socket获取输出流,out方法将获取的字符串输出

//通过输出流进行输出publicvoidout(Stringout

) {

String

outline=out+"\n"

;

try

{

//向客户端发送数据socket.getOutputStream().write(outline.getBytes("UTF-8"));

在ChatSocket的run方法中,将本ChatSocket的数据,通过socket获取输入流

读取本socket发送的信息,调用ChatManager的publish方法发送给其他ChatSocket

@Overridepublicvoid

run() {

try

{

//通过socket获取输入流,读取当前socket将要发送的信息

BufferedReader

reader=new

BufferedReader(

newInputStreamReader(socket.getInputStream(),"UTF-8"

));

String

line

;

//将本ChatSocket发送的数据,转发给其他客户端while((line=reader.readLine()) !=null

){

ChatManager.getChatManager().publish(

this,line

);

}

3.在Android中创建socket客户端

socket的创建不能在主线程中,新建异步线程,复写doInBackground方法,完成socket创建,连接与数据读取的操作。

//读取聊天信息的异步线程AsyncTask read =newAsyncTask() {

@OverrideprotectedVoiddoInBackground(Void... params) {

try{

//socket不能在主线程中//新建socket,参数为ip与端口号socket=newSocket(ip,12346);//通过socket的输入输出流,创建BufferedWriter与BufferedReaderwriter=newBufferedWriter(newOutputStreamWriter(socket.getOutputStream()));reader=newBufferedReader(newInputStreamReader(socket.getInputStream()));//向外发布成功的状态publishProgress("@success");}catch(IOException e) {

Toast.makeText(getApplicationContext(),"无法建立连接",Toast.LENGTH_SHORT).show();e.printStackTrace();}

try{

String line;//通过reader读取数据并向外发布while((line =reader.readLine())!=null){

publishProgress(line);}

}catch(IOException e) {

e.printStackTrace();}

return null;

复写onProgressUpdate()方法用于接收doInBackground方法向外发布的数据,更新主线程的ui

@Overrideprotected voidonProgressUpdate(String... values) {

//接收判断,如果是成功,则弹出提示if(values[0].equals("@success")){

Toast.makeText(MainActivity.this,"连接成功",Toast.LENGTH_SHORT).show();}

//在主ui线程中,更新接收到的消息tvChat.append("某人说:"+values[0]+"\n");super.onProgressUpdate(values);}

};

调用异步线程执行

//调用异步线程执行read.execute();

创建send方法,通过writer向外输出数据

public voidsend(){

try{

tvChat.append("我说:"+etSend.getText().toString()+"\n");//通过writer输出信息writer.write(etSend.getText().toString()+"\n");writer.flush();//清空ediText的内容etSend.setText("");}catch(IOException e) {

e.printStackTrace();}

button的事件监听器中调用相应的方法,添加互联网访问权限

@Overridepublic voidonClick(View v) {

switch(v.getId()){

caseR.id.btnConnect:

connect();break;caseR.id.btnSend:

send();break;}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容