通信是网络编程中重要的组成部分,而socket编程是网络编程的基础。利用socket可以实现客户端和服务器端的通信。下面我先把客户端和服务器端的代码粘上去再进行详细的分析。
package test1;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.junit.Test;
public class test2 {
@Test
public void client(){
Socket socket = null;
OutputStream oo = null;
FileInputStream fis = null;
InputStream io = null;
try {
//1.建立socket对象实例
socket = new Socket("127.0.0.1", 8989);
//2.调用getOutputStream()方法,目的是建立数据缓冲区,将数据发送到服务器端
oo = socket.getOutputStream();
//3.创建FileInputStream对象实例,将要发送的文件写入到输出流数据缓冲区中
File file=new File("D:\\123.avi");
fis = new FileInputStream(file);
byte[] b=new byte[1024];
int len;
while((len=fis.read(b))!=-1){
oo.write(b, 0, len);
}
//这行代码的意思是告诉服务器端我发送的数据完毕。
socket.shutdownOutput();
//4.调用getInputStream()方法:目的是接收从服务器端发送的数据
io = socket.getInputStream();
byte[] b1=new byte[1024];
int len1;
while((len1=io.read(b1))!=-1){
String str=new String(b1, 0, len1);
System.out.println(str);
}
} catch (Exception e) {
// 关闭各个连接
e.printStackTrace();
}finally{
if(io != null){
try {
io.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fis !=null){
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(oo != null){
try {
oo.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(socket !=null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@Test
public void server(){
ServerSocket ss = null;
Socket s = null;
InputStream is = null;
FileOutputStream fos = null;
OutputStream os = null;
try {
//1.创建ServerSocket对象的实例。
ss = new ServerSocket(8989);
//2.调用accept()方法来创建通信连接,期间经历了三次握手,只不过我们看不到
s = ss.accept();
//3.调用getInputStream()方法来接收客户端发送的文件
is = s.getInputStream();
//4.创建FileOutputStream()对象实例来保存从客户端发送的文件,并将文件写入到对象中
fos = new FileOutputStream(new File("D:\\123567.avi"));
byte[] b=new byte[1024];
int len;
while((len=is.read(b))!=-1){
fos.write(b, 0, len);
}
//5.向客户端反馈信息,将信息储存在数据缓冲区中
os = s.getOutputStream();
os.write("你发送的视频我已经接收".getBytes());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(os !=null){
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(is !=null){
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(s != null){
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(ss != null){
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
基本知识点补充:
上述代码块中我利用了junit进行模块测试,利用junit进行测试需要导入junit-4.12.jar和hamcrest-core-1.3.jar这两个jar包。在上面的代码中用到的知识点有socket,输入流(InputStream)和输出流(OutputStream)以及文件输入流(FileInputStream)和文件输出流(FileOutputStream)。
1.
从客户端(Client)来看:socket.getInputStream()方法是接收服务端发送的数据。socket.getOutputStream()方法是类似于一个数据缓冲器,用于存储向服务器端发送的数据。
从服务器端(Server)来看: socket.getInputStream()方法是接收客户端发送的数据。socket.getOutputStream()方法是类似于一个数据缓冲器,用于存储向客户端发送的数据。
2.
FileInputStream:文件输入流是用来读入数据的 ----------->读入
FileOutputStream:文件输出流是用来写出数据的----------->写出
3.计算机网络中三次握手实现原理
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 完成三次握手,客户端与服务器开始传送数据.
如果大家有什么疑问的可以提出问题我来一一为大家解答。