Socket 网络通信
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 网络通信的更多相关文章
- Socket网络通信之NIO
Socket网络通信之NIO NIO:new io ,java1.4开始推出的可非阻塞IO. java.nio 包,可解决BIO阻塞的不足 但比BIO学习.使用复杂. 可以以阻塞.非阻塞两种方式工作. ...
- Socket网络通信之BIO
Socket网络通信之BIO 如果要让两台计算机实现通信,需要的条件:ip,port,协议. 目前我们用的最多的就是TCP/IP协议和UDP协议.TCP三次握手,所以比较慢,且安全:UDP速度快,但是 ...
- socket网络通信
1.socket通常也称作"套接字",用于描述IP地址和端口.在internet上的主机一般运行了多个服务软件,同时提供几种服务,每种服务都打开一个socket,并绑定到一个端口上 ...
- java实现最基础的socket网络通信
一.网络通信基础 网络中存在很多的通信实体,每一个通信实体都有一个标识符就是IP地址. 而现实中每一个网络实体可以和多个通信程序同时进行网络通信,这就需要使用端口号进行区分. 二.java中的基本网络 ...
- Socket网络通信编程(二)
1.Netty初步 2.HelloWorld 3.Netty核心技术之(TCP拆包和粘包问题) 4.Netty核心技术之(编解码技术) 5.Netty的UDP实现 6.Netty的WebSocket实 ...
- TCP/UDP,SOCKET网络通信,C++/Java实现
趁这两天没事干,就把网络通信这一块搞一搞,C/S方面的了解一下,很重要! TCP Server/Client
- UDP SOCKET网络通信 C#
接收端 using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Thread ...
- [Socket]BSD Socket网络通信
http://blog.csdn.net/dongfengsun/article/details/4802925 文章有一些错误 #define KENTER @"/r/n" 应该 ...
- Socket网络通信之数据传递
Socket通信的步骤: 1.创建ServerSocket和Socket 2.打开连接到Socket的输入/输出流 3.按照协议对Socket进行读/写操作 4.关闭输入输出流.关闭Socket 服务 ...
随机推荐
- Django 之缓存
一.缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcac ...
- sass基础—具体编译步骤及对应命令:详细
/*基础语法*/h1{ color: red;} /*变量定义*/ $color: red; /*嵌套*/body{ header{ } footer{ }} /*mixin函数*/@mixin al ...
- python多线程爬取-今日头条的街拍数据(附源码加思路注释)
这里用的是json+re+requests+beautifulsoup+多线程 1 import json import re from multiprocessing.pool import Poo ...
- 有一个字典对象,d = {'a':1,'b':2},请用尽量简洁的代码将d转换成{1: 'a', 2: 'b'}
题目:有一个字典对象,d = {'a':1,'b':2},请用尽量简洁的代码将d转换成{1: 'a', 2: 'b'} 第一种方法: d = {'a': 1, 'b': 2}d = {value: k ...
- 【第一部分】10Leetcode刷题
一.删除链表的倒数第N个节点 题目:19. Remove Nth Node From End of List 分析:典型的利用双指针法解题.首先让指针first指向头节点,然后让其向后移动n步,接着让 ...
- eclipse中文乱码修改新方法
方法背景:想看别人的JAVA项目,导入eclipse后出现中文乱码,在设置了所有的工作空间都为UTF-8以后都没有用,并且项目Resource选项没有GBK选项,或统一选择GBK后会使其他项目出现中文 ...
- python之requests urllib3 连接池
0.目录 1.参考 2. pool_connections 默认值为10,一个站点主机host对应一个pool (4)分析 host A>>host B>>host A pag ...
- [转]Oh My Zsh,安装,主题配置
https://swp-song.com/2017/08/20/Tools/OhMyZsh%E5%AE%89%E8%A3%85%E5%92%8C%E4%B8%BB%E9%A2%98%E9%85%8D% ...
- C# 之 索引器
索引器允许类或者结构的实例按照与数组相同的方式进行索引取值,索引器与属性类似,不同的是索引器的访问是带参的. 索引器和数组比较: (1)索引器的索引值(Index)类型不受限制 (2)索引器允许重载 ...
- mysql实现简单的增删改查,放入xmapp自带数据库中
1.mysql概念:SQL-Structured Query Language,是一种特殊的语言,专用于操作关系型数据库服务器中的数据,所有的SQL语句分为四类: (1)DDL(2)DQL(3)DML ...