Socket 网络通信

时间:2022-08-28 10:57:46

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&sol;UDP,SOCKET网络通信,C&plus;&plus;&sol;Java实现

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

  7. UDP SOCKET网络通信 C&num;

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

  8. &lbrack;Socket&rsqb;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. angular

  2. MFC版美女找茬

    今天心情:捡了个闲暇. 前几天工作出了个漏洞,电话会议时候怎么都是忽大忽小的声音,实在没听清电话会议的内容,完了依据想象交了一个设计方案,之后便是赋闲. 进入正题,美女找茬实现不难,没有设计上的难度, ...

  3. 玩转ButterKnife注入框架

    在去年这个时候,我写过一篇介绍Android注解的文章android注解使用详解,这篇文章主要是介绍了Android中的AndroidAnnotations注入框架,AA框架有它自身的一些优点,这里不 ...

  4. 读取Maven项目下resources目录下的配置文件&lpar;properties为例&rpar;

    配置文件:xxxxx.properties a.url=******************** b.url=---------------------------------- 读取配置文件: im ...

  5. 记作为前端开发人员跑去面试C&num;&period;NET

    先谈结果,"秦总",与我面试讨论一个半小时,十分感动,然后拒绝了我. 本月17日16时许,收到邀请,于18日9时到司面试,虽如今仅深入前端领域,皆因曾有1年ASP.NET(C#)的 ...

  6. python开发&lowbar;tarfile&lowbar;文档归档压缩&vert;解压缩

    ''' python中的tarfile模块实现文档的归档压缩和解压缩 功能: 把工作空间下面的所有文件,打包生成一个tar文件 同时提供一个方法把该tar文件中的一些文件解压缩到 指定的目录中 ''' ...

  7. 【PAT】1028&period; List Sorting &lpar;25&rpar;

    题目链接:http://pat.zju.edu.cn/contests/pat-a-practise/1028 题目描述: Excel can sort records according to an ...

  8. 公用的css

    /*公共开始*/ body, ol, ul, h1, h2, h3, h4, h5, h6, p, th, td, dl, dd, form, fieldset, legend, input, tex ...

  9. 【Python数据挖掘】回归模型与应用

    线性回归 ( Linear Regression ) 线性回归中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归称为一元线性回归. 如果回归分析中包括两个或两个以上的自变量, ...

  10. Nginx配置(需要把nginx的根目录指向ftp上传文件的目录。)

    改成