Socket 网络通信

1.OSI (Open System Interconnect Reference Model)(开放系统互联参考模型)

从下低到高 :物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

2.TCP/IP

TCP/IP 是一个协议族,里边包括很多协议,TCP,IP知识两个很重要的协议。

TCP(Transmission Control Protocol,传输控制协议) 是面向连接的协议,在收发数据时,都需要与对面建立连接,TCP协议能够确保数据在传输过程中不会遗失。它的缺点是过程复杂,消耗的资源更多。

UDP(User Datagram Protocol)用户数据报协议,相比TCP就是无需建立连接,结构简单,无法保证正确性,容易丢包。

3.Socket 实现网络通信

Socket(套接字),用来描述IP地址和端口,是通信链的句柄,应用程序可以通过Socket向网络发送请求或者应答网络请求。Socket是支持TCP/IP协议的网络通信的基本操作单元。

3.1 实现服务端和客户端连接

服务端:

    // 1.创建服务端 Socket 并绑定端口
ServerSocket serverSocket=new ServerSocket(6666);
String ip=InetAddress.getLocalHost().getHostAddress(); S.println("~ ~ ~ 服务端已开启。 IP:"+ip); // 2.调用 accept() 方法,等待客户连接
Socket socket=serverSocket.accept(); // 3.获取输入流
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); //4. 不断读取客户端信息
String info;
while ((info=bufferedReader.readLine())!=null){
S.println(info);
} socket.shutdownInput(); //关闭输入流
socket.close();//关闭连接

客户端:

private void acceptServer() throws IOException {

    // 1.创建客户端Socket,指定服务器地址和端口
Socket socket=new Socket(IP,PORT);
// 2.获取输出流
OutputStream outputStream=socket.getOutputStream();
String string = "Tiger connect to server.";
// 3.向输出流中写入数据
outputStream.write(string.getBytes());
outputStream.flush(); // *** 强制发送缓冲区数据 *** socket.shutdownOutput(); //关闭输出流
socket.close();//关闭连接
}

3.2 多个客户端之间通信

实际上是所有客户端都向服务端发送消息,然后服务端再将消息返回给所有客户端。

服务端:

public class Server {

    private static final int PORT = 6666; //端口
private List<Socket> list = new ArrayList<>(); //存储所有客户端
private ServerSocket serverSocket = null;
private ExecutorService myExecutorService = null; //线程池 public static void main(String[] args) throws IOException { new Server(); //在构造函数中开启服务端
} public Server() throws IOException { // 1.创建Socket 服务并指定端口
serverSocket = new ServerSocket(PORT);
// 2.创建线程池
myExecutorService = Executors.newCachedThreadPool();
S.println("Server is running...");
// 3.不断地等待客户端连接,当有客户端连接后,添加到Socket集合,开启新的线程到线程池中
Socket client = null;
while (true) {
client = serverSocket.accept();
list.add(client);
myExecutorService.execute(new Service(client));
}
} class Service implements Runnable { private Socket socket;
private BufferedReader br;
private String msg; public Service(Socket socket) throws IOException {
this.socket = socket; br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
msg = "User:" + socket.getInetAddress().getHostAddress() + " ~ join the chat group. The amount of online:" + list.size();
this.sendMessage();
} @Override
public void run() { try {
// 不断接受客户端发来的消息,直到客户端退出, “bye”
while (true) {
if ((msg = br.readLine()) != null) {
if (msg.equals("bye")) { //客户端退出 S.println(" ~~~ ~~~ ~~~ ~~~ ");
list.remove(socket);
socket.close();
msg = "User:" + socket.getInetAddress() + " exit. The amount of online:" + list.size();
this.sendMessage();
break; // *** 退出循环 ***
} else { //客户端发送消息
msg = socket.getInetAddress() + " say:" + msg;
this.sendMessage();
}
}
} } catch (IOException e) {
e.printStackTrace();
}
} //为连接上服务端的每个客户端发送消息
public void sendMessage() throws IOException { S.println(msg);
//向每个客户端发送消息
for (Socket socketClient : list) {
try {
PrintWriter pout = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socketClient.getOutputStream(),"UTF-8")),true);
pout.println(msg);
}catch (IOException e) {e.printStackTrace();}
}
}
}
}

客户端:

public class MainActivity extends AppCompatActivity implements Runnable {

    private final String IP = "10.0.2.2"; //IP
private final int PORT = 6666; //端口
private EditText etMessage;
private TextView tvMessage; private Socket socket;
private BufferedReader br;
private OutputStream outputStream;
private String msg; private PrintWriter pw;
private boolean bIsClosed = false; //是否退出 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //Init controls
etMessage = (EditText) findViewById(R.id.et_Message);
tvMessage = (TextView) findViewById(R.id.tv_Message); connectToServer();
new Thread(MainActivity.this).start();
} //连接到服务端
private void connectToServer() { new Thread(new Runnable() {
@Override
public void run() {
try {
// 1.创建客户端Socket,指定服务器地址和端口
socket = new Socket(IP, PORT);
// 2.获取输入流
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 3.获取输出流
outputStream = socket.getOutputStream();
pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)), true); } catch (IOException e) {
e.printStackTrace();
}
} }).start();
} public void onClick(View view) throws IOException { //Send message
msg = etMessage.getText().toString();
sendMessage();
} public void sendMessage(){ //Socket 已经连接,并且输出流没有关闭
if (socket.isConnected() && !socket.isOutputShutdown()) {
new Thread(new Runnable() {
@Override
public void run() {
if (bIsClosed)
pw.println("bye");
else
pw.println(msg);
}
}).start();
}
} @Override
public void run() { try {
//不断地从输入流中读取数据
while (true) {
//Socket已经连接
if (socket != null) {
if ((msg = br.readLine()) != null) { runOnUiThread(new Runnable() {
@Override
public void run() {
tvMessage.setText(tvMessage.getText().toString() + msg + "\n");
}
});
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
} @Override
protected void onDestroy() { bIsClosed = true;
sendMessage();
super.onDestroy();
}
}

3.3 Socket 上传文件

服务端:

    // 1.创建服务端 Socket 并绑定端口
ServerSocket serverSocket=new ServerSocket(8888);
S.println("~~~ Server is running,waiting for client ~~~");
// 2.调用 accept() 方法,等待客户连接
Socket socket=serverSocket.accept();
// 3.获取输入流
InputStream inputStream = socket.getInputStream();
// 4.获取文件名称
String fileName="";
int len2;
while ((len2=inputStream.read())!=-1){
if(len2=='\t')
break;
else
fileName+=String.valueOf ((char)(len2));
}
// 5.创建文件,用来存储用户上传数据
FileOutputStream outputStream=new FileOutputStream(fileName,true);
// 6.将用户上传文件保存到本地
int len;
byte[] buffer=new byte[1024];
while ((len=inputStream.read(buffer,0,buffer.length))!=-1){
outputStream.write(buffer,0,len);
}
outputStream.close();
inputStream.close();
socket.shutdownInput(); //关闭输入流
socket.close();//关闭连接

客户端:

    new AsyncTask<Void, Integer, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
//1.创建Socket对象并获取输出流
Socket socket = new Socket(IP, PORT);
OutputStream outputStream = socket.getOutputStream();
// 2.写入文件名称,最后使用 \t 分割
outputStream.write("Video5.mp4\t".getBytes());
// 3.读取文件内容
InputStream inputStream=getResources().openRawResource(R.raw.video);
// 4.上传文件
int len;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) { outputStream.write(buffer, 0, len);
outputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
Toast.makeText(UDPActivity.this, "Upload successfully.", Toast.LENGTH_SHORT).show();
}
}.execute();

3.4UPD 通信

服务端:

   //1.创建服务端 DatagramSocket 指定端口
DatagramSocket socket=new DatagramSocket(8888);
//2.创建数据报,用于接受客户端发送的数据
byte[] data=new byte[1024]; //指定接受数据包的大小
DatagramPacket packet=new DatagramPacket(data,data.length);
//3.接受客户端发送的数据
S.println("~~~ Server is running,waiting for client ~~~");
while (true){
socket.receive(packet);
//4.读取数据
String info=new String(data,0,data.length);
S.println("Client:"+ info);
if(socket.isClosed())
{
S.println("Client has been exit.");
break;
}
}
socket.close(); //关闭 Socket

客户端:

    new Thread(new Runnable() {
@Override
public void run() {
try {
//1.获取 InetAddress 对象,指定IP
InetAddress address = InetAddress.getByName(IP);
//2.要发送的信息
byte[] data = "Test".getBytes();
//3.创建 DatagramSocket,用来发送数据
DatagramSocket socket = new DatagramSocket();
//4.创建 DatagramPacket,用来存储要发送的数据,并指定目标IP和端口
DatagramPacket packet = new DatagramPacket(data, data.length, address, PORT);
//5.发送消息到服务端
socket.send(packet);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();

3.5UPD 发送文件

服务端:

   //1.创建服务端 DatagramSocket 指定端口
DatagramSocket socket=new DatagramSocket(8888);
S.println("~~~ Server is running,waiting for client ~~~");
//2.创建文件,用来存储用户上传数据
File file=new File("Video.mp4");
FileOutputStream outputStream=new FileOutputStream("Video.mp4",true);
//3.不断接受客户端发送的数据
while (true){
//4.创建数据报,用于接受客户端发送的数据
byte[] buffer=new byte[1024]; //指定接受数据包的大小
DatagramPacket packet=new DatagramPacket(buffer,buffer.length);
socket.receive(packet);
//5.将数据写入文件
outputStream.write(buffer,0,packet.getLength());
if(socket.isClosed())
break;
}
outputStream.close();
socket.close(); //关闭 Socket

客户端:

    new AsyncTask<Void, Integer, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
//1.创建Socket对象并获取输出流
Socket socket = new Socket(IP, PORT);
OutputStream outputStream = socket.getOutputStream();
// 2.写入文件名称,最后使用 \t 分割
outputStream.write("Video5.mp4\t".getBytes());
// 3.读取文件内容
InputStream inputStream=getResources().openRawResource(R.raw.video);
// 4.上传文件
int len;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) {
outputStream.write(buffer, 0, len);
outputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
Toast.makeText(UDPActivity.this, "Upload successfully.", Toast.LENGTH_SHORT).show();
}
}.execute();

学习自:http://www.runoob.com/w3cnote/android-tutorial-socket-intro.html

Socket 网络通信的更多相关文章

  1. Socket网络通信之NIO

    Socket网络通信之NIO NIO:new io ,java1.4开始推出的可非阻塞IO. java.nio 包,可解决BIO阻塞的不足 但比BIO学习.使用复杂. 可以以阻塞.非阻塞两种方式工作. ...

  2. Socket网络通信之BIO

    Socket网络通信之BIO 如果要让两台计算机实现通信,需要的条件:ip,port,协议. 目前我们用的最多的就是TCP/IP协议和UDP协议.TCP三次握手,所以比较慢,且安全:UDP速度快,但是 ...

  3. socket网络通信

    1.socket通常也称作"套接字",用于描述IP地址和端口.在internet上的主机一般运行了多个服务软件,同时提供几种服务,每种服务都打开一个socket,并绑定到一个端口上 ...

  4. java实现最基础的socket网络通信

    一.网络通信基础 网络中存在很多的通信实体,每一个通信实体都有一个标识符就是IP地址. 而现实中每一个网络实体可以和多个通信程序同时进行网络通信,这就需要使用端口号进行区分. 二.java中的基本网络 ...

  5. Socket网络通信编程(二)

    1.Netty初步 2.HelloWorld 3.Netty核心技术之(TCP拆包和粘包问题) 4.Netty核心技术之(编解码技术) 5.Netty的UDP实现 6.Netty的WebSocket实 ...

  6. TCP/UDP,SOCKET网络通信,C++/Java实现

    趁这两天没事干,就把网络通信这一块搞一搞,C/S方面的了解一下,很重要! TCP Server/Client

  7. UDP SOCKET网络通信 C#

    接收端 using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Thread ...

  8. [Socket]BSD Socket网络通信

    http://blog.csdn.net/dongfengsun/article/details/4802925 文章有一些错误 #define KENTER @"/r/n" 应该 ...

  9. Socket网络通信之数据传递

    Socket通信的步骤: 1.创建ServerSocket和Socket 2.打开连接到Socket的输入/输出流 3.按照协议对Socket进行读/写操作 4.关闭输入输出流.关闭Socket 服务 ...

随机推荐

  1. 《剑指offer》顺时针打印矩阵

    本题来自<剑指offer> 顺时针打印矩阵 题目: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 1 ...

  2. Spring JDBC概述

    1.jdbc 概述 Spring JDBC是Spring框架的持久层子框架.用于对数据库的操作(增删改查). 而JdbcTemplate它是spring jdbc子框架中提供的一个操作类,用于对原始J ...

  3. cf自训6

    cf946D 背包+区间dp 好题 /* 先预处理出每行消去i个1后可以的到的最小时间: 先求每行的前缀和,枚举左端点和右端点,消去的1 cost=tot-sum[r]+sum[l-1],区间长度=r ...

  4. 论文阅读笔记十八:ENet: A Deep Neural Network Architecture for Real-Time Semantic Segmentation(CVPR2016)

    论文源址:https://arxiv.org/abs/1606.02147 tensorflow github: https://github.com/kwotsin/TensorFlow-ENet ...

  5. XAML绑定到资源文件字符串时失败

    参考:https://stackoverflow.com/questions/19586401/error-in-binding-resource-string-with-a-view-in-wpf ...

  6. webpack学习笔记--配置plugins

     Plugin Plugin 用于扩展 Webpack 功能,各种各样的 Plugin 几乎让 Webpack 可以做任何构建相关的事情. 配置 Plugin Plugin 的配置很简单, plugi ...

  7. java数组知识点总结

    数组是一个用来存储同一个数据类型多个元素的一个容器(数组长度是固定的,数组中存储的元素的数据类型要求一致) 1.格式: 格式1: 数据类型[] 数组名 = new 数据类型[数组长度]; 格式2: 数 ...

  8. 【CF526F】Pudding Monsters

    题意: 给你一个排列pi,问你有对少个区间的值域段是连续的. n≤3e5 题解: bzoj3745

  9. BZOJ 4282(慎二的随机数列

    题解: 网上题解还没看 我的方法是用平衡树维护一个单调栈 由于N用了一定是赚的 所以它的作用是让f[i+1]=f[i]+1 这个是可以记录的 就跟noip蚯蚓那题一样 然后插入一个值的时候查询前面的最 ...

  10. 解决win7 安装完jdk7后,再安装jdk8出现的问题 has value '1.8', but '1.7' is required.

    http://blog.csdn.net/qiyueqinglian/article/details/46605759 电脑装了jdk8,JAVA_HOME也是设置的8. 不删除8变回7. 改了JAV ...