使用Socket构建简易聊天室
来源:互联网 发布:模拟退火算法简单实例 编辑:程序博客网 时间:2024/05/22 05:29
Socket,简称套接字,由ip和port(端口号组成),例如:192.168.1.16:8080,Socket有两种主要的操作方式:面向连接的和无连接的,即TCP和UDP连接,面向连接的使用TCP协议。
Java在包Java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端,服务器端先通过ServerSocket开启服务,然后客户端才可通过新建一个Socket连接到服务器端。
首先先看一下服务器端的构建
这里通过Java代码实现服务器端的功能:
import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;public class MyServer {// 定义保存所有Socket的集合 public static ArrayList<Socket> sockets = new ArrayList<Socket>();public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(20000);System.out.println("服务器创建成功");System.out.println("等待客户端的连接.....");while (true) {Socket socket = serverSocket.accept();System.out.println("有客户端链接进来");sockets.add(socket);new Thread(new ServerThread(socket)).start();}}}服务器端线程代码:
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.net.Socket;public class ServerThread implements Runnable {// 定义当前线程所处理的Socketprivate Socket socket = null;// 该线程所处理的Socket所对应的输入流BufferedReader br = null;public ServerThread(Socket socket) throws UnsupportedEncodingException,IOException {this.socket = socket;// 初始化该Socket对应的输入流br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf-8"));}OutputStream os;@Overridepublic void run() {try {String content = null;// 采用循环不断从Socket中读取客户端发送过来的数据while ((content = readFromClient()) != null) {// 遍历socketList中的每个Socket,将读到的内容向每个Socket发送一次for (Socket s : MyServer.sockets) {os = s.getOutputStream();os.write((content + "\n").getBytes("utf-8"));String ss = MyServer.sockets.toString();System.out.println(ss);}}} catch (Exception e) {e.printStackTrace();}}/** * 定义读取客户端数据的方法 * * @return */private String readFromClient() {try {return br.readLine();}// 如果捕捉到异常,表明该Socket对应的客户端已经关闭catch (Exception e) {// 删除该Socket// MyServer.sockets.remove(socket);e.printStackTrace();}return null;}}创建好服务器端Java项目之后,再新建一个Android项目来创建客户端
客户端的代码实现如下:
import java.io.OutputStream;import java.net.Socket;import android.app.Activity;import android.content.Context;import android.net.wifi.WifiInfo;import android.net.wifi.WifiManager;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;public class MainActivity extends Activity {private EditText input;private EditText show;private Button sendBtn;private OutputStream os;private Handler handler;private Button main_btn_refresh;private String ip;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);input = (EditText) findViewById(R.id.main_et_input);show = (EditText) findViewById(R.id.main_et_show);sendBtn = (Button) findViewById(R.id.main_btn_send);main_btn_refresh = (Button) findViewById(R.id.main_btn_refresh);main_btn_refresh.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {getConnect();}});handler = new Handler() {@Overridepublic void handleMessage(Message msg) {// 如果消息来自子线程if (msg.what == 0x234) {// 将读取的内容追加显示在文本框中show.append("\n" + msg.obj.toString());}}};getConnect();ip = getIp();sendBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {try {// 将用户在文本框内输入的内容写入网络os.write((ip + ": " + input.getText().toString() + "\r\n").getBytes());// 清空input文本框数据input.setText("");} catch (Exception e) {e.printStackTrace();}}});}// 开启链接服务private void getConnect() {new Thread() {public void run() {Socket socket;try {Log.i("开启客户端请求", "请求打开");socket = new Socket("192.168.1.67", 20000);// 客户端启动ClientThread线程不断读取来自服务器的数据new Thread(new ClientThread(socket, handler)).start();os = socket.getOutputStream();} catch (Exception e) {e.printStackTrace();}};}.start();}public String getIp() {// 获取wifi服务WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);// 判断wifi是否开启if (!wifiManager.isWifiEnabled()) {wifiManager.setWifiEnabled(true);}WifiInfo wifiInfo = wifiManager.getConnectionInfo();int ipAddress = wifiInfo.getIpAddress();String ip = intToIp(ipAddress);return ip;}private String intToIp(int i) {return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF)+ "." + (i >> 24 & 0xFF);}}客户端线程实现:
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.Socket;import android.os.Handler;import android.os.Message;public class ClientThread implements Runnable {private Handler handler;// 该线程所处理的Socket所对应的输入流private BufferedReader br = null;public ClientThread(Socket socket, Handler handler) throws IOException {this.handler = handler;br = new BufferedReader(new InputStreamReader(socket.getInputStream()));}@Overridepublic void run() {try {String content = null;// 不断读取Socket输入流的内容while ((content = br.readLine()) != null) {// 每当读到来自服务器的数据之后,发送消息通知程序界面显示该数据Message msg = new Message();msg.what = 0x234;msg.obj = content;handler.sendMessage(msg);}br.close();} catch (Exception e) {e.printStackTrace();}}}Activity的布局文件:
<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="${relativePackage}.${activityClass}" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <EditText android:id="@+id/main_et_input" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="10" /> <Button android:id="@+id/main_btn_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="发送" /> <Button android:id="@+id/main_btn_refresh" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="重新连接" /> </LinearLayout> <EditText android:id="@+id/main_et_show" android:layout_width="match_parent" android:layout_height="match_parent" android:cursorVisible="false" android:editable="false" android:gravity="top" /></LinearLayout>最后在清单文件中加入下面的权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" > </uses-permission> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" > </uses-permission> <uses-permission android:name="android.permission.WAKE_LOCK" > </uses-permission>之后在两个客户端进行对话,
产生了下面的效果:
本文转载自:http://blog.csdn.net/u010142437/article/details/9327541
0 0
- 使用Socket构建简易聊天室
- socket简易聊天室
- java socket简易聊天室
- 安卓 socket简易聊天室
- Java简易聊天室程序socket
- Socket编程实现简易聊天室
- 使用node.js + socket.io 构建多个房间聊天室
- 【Socket编程】聊天室的构建
- C#简易版Socket聊天室 附源码
- Socket套接字做简易聊天室
- 基于Socket的局域网简易聊天室
- socket详解及简易聊天室编写
- java菜鸟 socket简易局域网聊天室
- php基于websocket搭建简易聊天室(socket)
- 使用Network实现简易聊天室
- 在Android操作系统中如何使用Socket编程实现简易聊天室
- PHP百行代码快速构建简易聊天室
- PHP百行代码快速构建简易聊天室
- linux内核对网卡驱动多队列的支持
- poj-1422
- Errors occurred during the build. Errors running builder 'JavaScript Validator' on
- java移位运算
- 通过MediaStore获取Audio信息
- 使用Socket构建简易聊天室
- 实现简单的动态数组
- TCP/IP模型的简单解释
- C++小知识之(Void**)类型的参数赋值
- PIE(二分法分饼)
- 修改加了important标记的css样式
- 理解*(void**)b .
- LinkedHashMap 排序
- 从30岁到35岁:为你的生命多积累一些厚度(上)