什么是Socket ?
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
简介 :
Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。
架构 :
我们先来写服务端,其实服务端就是一个Socket通信,java文件
public class ChartService {
//用来存储多个客户端发来的请求
List<Socket> client = new ArrayList<Socket>();
//开始 的启动方法
public void startServer(){
try {
ServerSocket ss = new ServerSocket(12345);
//我们写一个循环来让它一直处于监听的状态
while(true){
Socket socket = ss.accept();
client.add(socket);
this.new newThread(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//我们写一个线程来执行来存储客户端发来的聊天数据
class newThread extends Thread{
Socket s ;
BufferedReader bReader;
public newThread(Socket s) {
super();
this.s = s;
//用于接收数据
try {
bReader = new BufferedReader(new InputStreamReader(s.getInputStream(),"utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
super.run();
String data=null;
try {
while((data=bReader.readLine())!=null){
//遍历集合client
for(Socket s : client){
//輸出發送的數據
s.getOutputStream().write((data+"\n").getBytes());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//main方法,用於啟動java程序
public static void main(String[] args) {
new ChartService().startServer();
}
}
客户端,我们就要把数据传到服务端,再从服务端获取传过去的数据,显示在文本框中,,
<EditText
android:id="@+id/tv"
android:layout_width="fill_parent"
android:layout_height="300dp"
android:enabled="false"
/>
<EditText
android:id="@+id/et_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="昵称" />
<EditText
android:id="@+id/et_chart"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="请输入聊天" />
<Button
android:id="@+id/send"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="发送" />
public class MainActivity extends Activity implements OnClickListener {
private EditText et_name, et_chart;
private EditText show;
private Button send;
Socket socket;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 0x12) {
String chat = show.getText().toString();
String chat1 = msg.getData().getString("chart");
show.setText(chat + "\n\n" + chat1);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iviview();
try {
//设置本机的ip地址 端口号为服务端的端口号
socket = new Socket("172.20.58.145", 12345);
//利用线程来启动
new ChartTherad(socket, handler).start();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//初始化控件
private void iviview() {
et_name = (EditText) findViewById(R.id.et_name);
et_chart = (EditText) findViewById(R.id.et_chart);
show = (EditText) findViewById(R.id.tv);
send = (Button) findViewById(R.id.send);
send.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == send) {
String name = et_name.getText().toString();
String chart = et_chart.getText().toString();
String data = name + ":" + chart + "\n";
// 判断一下socket的值
if (socket != null) {
// 我们就输出这个data
try {
// 传给服务器输出流(也就是发送数据)
socket.getOutputStream().write(data.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ChartTherad extends Thread {
Socket client;
Handler handler;
public ChartTherad(Socket client, Handler handler) {
super();
this.client = client;
this.handler = handler;
}
@Override
public void run() {
super.run();
//用于接收从服务端获取的数据
BufferedReader br;
try {
// 接受传过来的输入流
br = new BufferedReader(new InputStreamReader(
client.getInputStream(), "utf-8"));
while (true) {
String content = br.readLine();
// 传给主线程 进行更新
Bundle bundle = new Bundle();
bundle.putString("chart", content);
Message msg = new Message();
msg.setData(bundle);
msg.what = 0x12;
handler.sendMessage(msg);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
<uses-permission android:name="android.permission.INTERNET"/>
注:4.0后会阻塞主线程的进程,因此都要开线程执行,这里主线程没有开线程,所以可用4.0以下版本的模拟器运行,,