TCP传输
TCP Socket:IP地址和端口,套接字
Socket和ServerSocket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数据的传输
关闭socket
同样,客户端与服务器端是两个独立的应用程序。
☆基本思路(客户端)
客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。
连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream(), getOutputStream()获取即可。
与服务端通讯结束后,关闭Socket。
☆基本思路(服务器端)
服务端需要明确它要处理的数据是从哪个端口进入的。
当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。
当该客户端访问结束,关闭该客户端。
基于TCP的Socket通信流程
☆客户端
通过Socket建立对象并指定要连接的服务端主机以及端口。
Socket s = new Socket(“192.168.1.1”,9999);
OutputStream out = s.getOutputStream();
out.write(“hello”.getBytes());
s.close();
☆服务器端
ServerSocket ss = new ServerSocket(9999);
Socket s = ss.accept ();
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int num = in.read(buf);
String str = new String(buf,0,num);
System.out.println(s.getInetAddress().toString()+”:”+str);
s.close();
ss.close();
1.下面模拟一下TCP传输协议传输
客户端:
package cn.hncu.net.tcp.demo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @authordragon_Dai
* @version 2017-8-13 下午8:51:29
* @filename MySocketClient.java
*
* TCP传输编程
* 客户端:(Socket)
* 服务器:(ServerSocket)
*/
public class MySocketClient {
public static void main(String[] args) {
try {
//创建一个Socket对象
//尝试向指定"IP+端口号"的那台服务器发出"握手"申请,如果握手等待时间超时则会抛出异常.
Socket s=new Socket("127.0.0.1", 10005);
//如果程序可以运行到此处,说明上一句代码每一出现异常,表示"握手"成功,接下来就可以通过s和对方(服务器)进行通讯了
//通过流来向服务器发送传输的信息
OutputStream os=s.getOutputStream();
os.write("来自客户端的传输信息".getBytes());
//接收服务器返回的提示信息
InputStream is=s.getInputStream();
int len=-1;
byte bs[]=new byte[512];
while((len=is.read(bs))!=-1){
System.out.println(new String(bs, 0, len));
}
//关流
os.close();
is.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服务器:
package cn.hncu.net.tcp.demo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @authordragon_Dai
* @version 2017-8-13 下午9:05:05
* @filename MySocketServer.java
*
* TCP传输编程
* 客户端:(Socket)
* 服务器:(ServerSocket)
*/
public class MySocketServer {
public static void main(String[] args) {
try {
//创建一个ServerSocket对象
ServerSocket server=new ServerSocket(10005);//指定服务器的端口号
while(true){ //服务器一打开就一直等待客户端来通讯(握手)
Socket s = server.accept(); //阻塞方法,返回值为对方的Socket对象
//程序运行到此处说明上一句每一异常,表示握手成功.
//通过流来读取客户端传输过来的信息
InputStream in=s.getInputStream();
String ip=s.getInetAddress().getHostAddress();
System.out.println("ip:"+ip);
int len=-1;
byte bs[]=new byte[512];
len=in.read(bs);
System.out.println(new String(bs, 0, len));
//读取完之后,向客户端,返回一些提示信息.
//通过流来返回信息
OutputStream os=s.getOutputStream();
os.write("来自服务器的提示信息".getBytes());
//关流
os.close();
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端显示
来自服务器的提示信息
服务器显示
ip:127.0.0.1
来自客户端的传输信息
2.下面模拟客户端读取一个本地文本文件,发向服务器,服务器存储起来package cn.hncu.net.tcp.uploadTextFile;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @authordragon_Dai
* @version 2017-8-13 下午9:49:22
* @filename UploadTextClient.java
*
*读取一个本地文本文件,将数据发送到服务端,服务器端对数据进行存储。
* 存储完毕后,给客户端一个提示。
*/
public class UploadTextClient {
public static void main(String[] args) {
try {
//创建一个Socket对象
Socket s=new Socket("127.0.0.1",10006);
//1.向服务器上传文件
//目的
BufferedReader br=new BufferedReader(new FileReader("wenben.txt"));
//源
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
String str=null;
while((str=br.readLine())!=null){
pw.println(str);
}
//这里因为下面还需要接收服务器返回的信息,而服务器一直在读,所以这里需要告诉服务器,写入数据完毕
s.shutdownOutput();
//2.接收服务器返还信息
BufferedReader br2=new BufferedReader(new InputStreamReader(s.getInputStream()));
String str2=null;
while((str2=br2.readLine())!=null){
System.out.println(str2);
}
//关流
br.close();
pw.close();
br2.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器
package cn.hncu.net.tcp.uploadTextFile;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @authordragon_Dai
* @version 2017-8-13 下午9:54:54
* @filename UploadTextServer.java
*
*读取一个本地文本文件,将数据发送到服务端,服务器端对数据进行存储。
* 存储完毕后,给客户端一个提示。
*/
public class UploadTextServer {
public static void main(String[] args) {
try {
//创建一个ServerSocket对象
ServerSocket server=new ServerSocket(10006);//指定服务器的端口号
while(true){
Socket s=server.accept(); //阻塞方法,返回值为对方的Socket对象
//程序运行到此处说明上一句每一异常,表示握手成功.
//通过流来读取客户端传输过来的信息
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
//存入到File中。
//I/O 流的介绍 与使用 总结,在前面的博客中有写过。
PrintWriter pw=new PrintWriter(new FileWriter("server.txt"),true); //自动刷缓存
String str=null;
while((str=br.readLine())!=null){
pw.println(str);
}
//读取完毕之后,给客户端发送读取完毕的信息
PrintWriter pw2=new PrintWriter(s.getOutputStream(),true);
pw2.println("上传成功");
//关流
br.close();
pw.close();
pw2.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端读取的wenben.txt
本地文本文件
-------over
客户端收到服务器的提示信息:(我这里是在MyEclipse的控制台显示)
上传成功
服务器存储的server.txt文件:
本地文本文件
-------over
3.下面客户端向服务器发送图片
客户端:
package cn.hncu.net.tcp.uploadPicFile;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
/**
* @authordragon_Dai
* @version 2017-8-13 下午11:48:46
* @filename UploadPicClient.java
*
* 客户端需求:把一个图片文件发送到服务端并读取回馈信息。
* 要求判断文件是否存在及格式是否为jpg或gif并要求文件小于2M。
* 服务端需求:接收客户端发送过来的图片数据。进行存储后,回馈一个 上传成功字样。
* 支持多用户的并发访问(这里需要多线程)。
*/
public class UploadPicClient {
public static void main(String[] args) {
//先让用户选择文件
JFileChooser jfc=new JFileChooser();
int res = jfc.showOpenDialog(null);
//选中了文件才进行通讯
if(res==JFileChooser.APPROVE_OPTION){
//卫条件
if(!jfc.getSelectedFile().getName().endsWith(".jpg")
&& !jfc.getSelectedFile().getName().endsWith(".gif")){
JOptionPane.showMessageDialog(null, "文件格式选择错误,只能选择.jpg或者.gif文件");
return;
}
if(jfc.getSelectedFile().length()>1024*1024*2){
JOptionPane.showMessageDialog(null, "文件不能大于2M");
return;
}
try {
Socket s=new Socket("127.0.0.1",10007);
//源 file
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(jfc.getSelectedFile()));
//目的 Socket
BufferedOutputStream bos=new BufferedOutputStream(s.getOutputStream());
byte bs[]=new byte[512];
int len=-1;
while((len=bis.read(bs))!=-1){
bos.write(bs, 0, len);
}
bos.flush(); //缓存流需要刷缓存
s.shutdownOutput(); //提示服务器,传输数据完毕
//接收服务器返回的提示信息
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
String str=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
//关流
bis.close();
bos.close();
br.close();
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务器
package cn.hncu.net.tcp.uploadPicFile;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @authordragon_Dai
* @version 2017-8-13 下午11:46:50
* @filename UploadPicServer.java
*
* 客户端需求:把一个图片文件发送到服务端并读取回馈信息。
* 要求判断文件是否存在及格式是否为jpg或gif并要求文件小于2M。
* 服务端需求:接收客户端发送过来的图片数据。进行存储后,回馈一个 上传成功字样。
* 支持多用户的并发访问(这里需要多线程)。
*/
public class UploadPicServer {
public static void main(String[] args) {
try {
ServerSocket server=new ServerSocket(10007);
while(true){
Socket s=server.accept();
new Thread(new UploadThread(s)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class UploadThread implements Runnable{
private Socket s;
public UploadThread(Socket s) {
this.s=s;
}
@Override
public void run() {
String ip=s.getInetAddress().getHostAddress();
System.out.println("ip="+ip+" 连接到服务器");
//接收文件
try {
BufferedInputStream bis=new BufferedInputStream(s.getInputStream());
//服务器接收到的文件,存储到新的文件,新的文件命名(在这里我通过 ip+"count++"+".jpg")
File dir=new File("pics");
if(!dir.exists()){
dir.mkdirs();
}
int count=1;
File file=new File(dir,ip+(count++)+".jpg");
while(file.exists()){
file=new File(dir,ip+(count++)+".jpg");
}
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file));
byte bs[]=new byte[512];
int len=-1;
while((len=bis.read(bs))!=-1){
bos.write(bs, 0, len);
}
bos.flush(); //缓存流需要刷缓存
//给服务器返回信息
OutputStream os=s.getOutputStream();
os.write("上传成功".getBytes());
//关流
bis.close();
bos.close();
os.close();
s.close();
} catch (IOException e) {
//如果发生异常,向客户端发送上传失败的信息
try {
OutputStream os=s.getOutputStream();
os.write("上传失败".getBytes());
} catch (IOException e1) {
throw new RuntimeException("Socket出现异常");
}
}
}
}
这里客户端可以多次运行,向服务器发送图片文件.