利用Socket进行普通通信
-
TCP:(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议.
-
UDP:(UDP,User Datagram Protocol)无连接的协议,在传输数据之前,客户端和服务器端不建立和维护连接,提供不可靠的数据传输。
-
Socket(套接字):基于TCP协议的网络通信,可以提供双向安全连接的网络通信。Socket利用数据流来完成数据的传递工作。
-
使用步骤:
1.建立连接
2.通过Socket生成InputStream/OutputStream(准备发送数据)
3.使用InputStream/OutputStream进行发送数据和接收数据
4.关闭InputStream、OutputStream、Socket -
服务端代码
package org.dsl.socketDome;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class MyService {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket accept = null;
InputStream in = null;
BufferedReader reader = null;
OutputStream out = null;
try {
//接收连接
serverSocket = new ServerSocket(8080);
System.out.println("准备连接。。。。");
accept = serverSocket.accept();
System.out.println("服务端接收到连接");
in = accept.getInputStream();
//利用转换流:字节流-->转换流-->字符流,如果不使用BufferedReader字符流,
//则需要定义缓冲数组(字节缓冲或者字符缓冲)用来接收数据
reader = new BufferedReader(new java.io.InputStreamReader(in));
String str = null;
while ((str = reader.readLine())!=null) {
System.out.println(str);
}
accept.shutdownInput();
//发出数据
out = accept.getOutputStream();
out.write("欢迎访问服务器".getBytes());
accept.shutdownOutput();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(out!=null) out.close();
if(reader!=null)reader.close();
if(in!=null)in.close();
if(accept!=null)accept.close();
if(serverSocket!=null)serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- 客户端代码
package org.dsl.socketDome;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class MyClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream out = null;
InputStream in = null;
BufferedReader reader = null;
try {
//建立连接
socket = new Socket("127.0.0.1",8080);
//发送数据
out = socket.getOutputStream();
out.write("hello server".getBytes());
socket.shutdownOutput();
//接收数据
in = socket.getInputStream();
reader = new BufferedReader(new java.io.InputStreamReader(in));
String str = null;
while ((str=reader.readLine())!=null) {
System.out.println(str);
}
socket.shutdownInput();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(out!=null)out.close();
if(socket!=null)socket.close();
if(reader!=null)reader.close();
if(in !=null)in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
-
特别关注
1.服务端代码使用ServerSocket类(底层还是产生Socket类的对象)来产生对象,并且调用accept()方法来进行拦截客户端的通信请求,进行实时通信。
2.客户端代码是利用Socket类来产生对象,进行通信的。
3.需要利用shutdownOutput()、shutdownIutput()在输入输出后,作用是先前写入的数据将被发送后正常关闭TCP连接,如果不写则通信将不会把信息成功传输。
4.在程序的最后要进行,将流关闭,原则:先写后关,先关外,再关内。
利用Socket进行对象通信
前提条件
- 实体类必须实现Serializable进行序列化;
- 信息的收发必须使用对象流ObjectOutputStream/ObjectIutputStream。
- 实体类代码
package org.dsl.objectSocket;
import java.io.Serializable;
public class Student implements Serializable {
private String name;
private int sex;
private int age;
public Student() {
}
public Student(String name, int sex, int age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", sex=" + sex + ", age=" + age + "]";
}
}
- 服务端代码:
package org.dsl.objectSocket;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class myServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket =null;
InputStream in = null;
ObjectInputStream object = null;
try {
//建立连接
serverSocket = new ServerSocket(8080);
socket = serverSocket.accept();
System.out.println("服务端接收到连接");
//利用socket建立InputStream/OutputStream
in = socket.getInputStream();
//利用转换流将字节流,装换为对象流
object = new ObjectInputStream(in);
//装换为Student类
Student student = (Student)object.readObject();
System.out.println("接收到的数据:"+student);
//进行关闭操作
socket.shutdownInput();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(object!=null)object.close();
if(in!=null)in.close();
if(socket!=null)socket.close();
if(serverSocket!=null)serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- 客户端代码:
package org.dsl.objectSocket;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class myClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream out = null;
ObjectOutputStream object = null;
try {
// 进行连接
socket = new Socket("localhost", 8080);
// 创建对象
Student student = new Student("zs", 1, 20);
out = socket.getOutputStream();
// 将字节流对象转换为对象流
object = new ObjectOutputStream(out);
System.out.println("准备将对象发送。。。。");
object.writeObject(student);
System.out.println("对象发送完毕!");
// 进行关闭
socket.shutdownOutput();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (object != null)object.close();
if(out!=null)out.close();
if(socket!=null)socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
利用多线程实现多个客户端访问服务器
- 服务器端代码
package org.dsl.threadSocket;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(8080);
while(true) {
socket = serverSocket.accept();
ThreadServer threadServer = new ThreadServer(socket);
threadServer.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(socket!=null)socket.close();
if(serverSocket!=null)serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- 多线程端代码
package org.dsl.threadSocket;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ThreadServer extends Thread{
Socket socket;
InputStream in = null;
ObjectInputStream ois = null;
OutputStream out = null;
public ThreadServer(Socket socket) {
super();
this.socket = socket;
}
@Override
public void run() {
try {
in = socket.getInputStream();
ois = new ObjectInputStream(in);
Student student = (Student)ois.readObject();
System.out.println(student);
socket.shutdownInput();
//接收成功返回信息
out = socket.getOutputStream();
out.write("成功接收到数据。。。".getBytes());
socket.shutdownOutput();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(out!=null)out.close();
if(ois!=null)ois.close();
if(in!=null)in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- 客户端一代码
package org.dsl.threadSocket;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class myClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream out = null;
ObjectOutputStream object = null;
try {
// 进行连接
socket = new Socket("localhost", 8080);
// 创建对象
Student student = new Student("zs", 1, 20);
out = socket.getOutputStream();
// 将字节流对象转换为对象流
object = new ObjectOutputStream(out);
System.out.println("准备将对象发送。。。。");
object.writeObject(student);
System.out.println("对象发送完毕!");
// 进行关闭
socket.shutdownOutput();
//接收服务器返回结果
InputStream in = socket.getInputStream();
byte[] buf = new byte[100];
in.read(buf);
System.out.println("服务端返回:"+new String(buf));
socket.shutdownInput();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (object != null)object.close();
if(out!=null)out.close();
if(socket!=null)socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- 客户端二代码:
package org.dsl.threadSocket;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class myClient2 {
public static void main(String[] args) {
Socket socket = null;
OutputStream out = null;
ObjectOutputStream object = null;
try {
// 进行连接
socket = new Socket("localhost", 8080);
// 创建对象
Student student = new Student("lisi", 0, 21);
out = socket.getOutputStream();
// 将字节流对象转换为对象流
object = new ObjectOutputStream(out);
System.out.println("准备将对象发送。。。。");
object.writeObject(student);
System.out.println("对象发送完毕!");
// 进行关闭
socket.shutdownOutput();
//接收服务器返回结果
InputStream in = socket.getInputStream();
byte[] buf = new byte[100];
in.read(buf);
System.out.println("服务端返回:"+new String(buf));
socket.shutdownInput();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (object != null)object.close();
if(out!=null)out.close();
if(socket!=null)socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- 特别关注
利用线程实现多客户端访问服务器,实际的收发信息是在线程中的run()方法中实现的,需要借助有参构造器实现多个socket的分配。
使用DatagramSocket实现UDP协议
- UDP的通信是要依靠DatagramPacket和DatagramSocket对象来实现的,DatagramPacket是类似于装载信息的“箱子”,而DatagramSocket是获取数据的手段,发送数据时,需要先定义DatagramPacket“箱子”,其中箱子要有数据才可以,通过DatagramSocket将数据发送出去;在接收数据时,也需要先定义DatagramPacket“箱子”,再定义DatagramSocket对象,利用DatagramSocket对象将数据拿到,然后在装入DatagramPacket箱子中,在之后的代码实际上都是使用DatagramPacket对象进行操作的。
- UDP是无连接的通信,所以无需象TCP通信时,将所有对象全部关闭才可以,只需要关闭DatagramSocket对象即可。
- 服务器端代码:
package org.dsl.udpdemo;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class MyServer {
public static void main(String[] args) {
DatagramPacket dp = null;
DatagramSocket ds = null;
try {
//定义字节缓冲数组
byte[] data = new byte[64];
//
dp = new DatagramPacket(data,data.length);
ds = new DatagramSocket(8080);
//将接收的数据放入dp中
ds.receive(dp);
//显示接收数据
String str = new String (dp.getData(),0,data.length);
System.out.println("接收返回数据:"+str);
System.out.println("发送方地址:"+dp.getAddress().getHostAddress());
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
ds.close();
}
}
}
- 客户端代码:
package org.dsl.udpdemo;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class MyClient {
public static void main(String[] args) {
DatagramPacket dp = null;
DatagramSocket ds = null;
try {
String msg = "hello...";
InetAddress byName;
byName = InetAddress.getByName("127.0.0.1");
dp = new DatagramPacket(msg.getBytes(),0,msg.length(),byName,8080);
ds = new DatagramSocket();
ds.send(dp);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
ds.close();
}
}
}