0
点赞
收藏
分享

微信扫一扫

网络编程(三)--TCP


TCP Socket:IP地址和端口,套接字

1)Socket和ServerSocket
2)建立客户端和服务器端
3)建立连接后,通过Socket中的IO流进行数据的传输
4)关闭socket         
同样,客户端与服务器端是两个独立的应用程序。

 

☆基本思路(客户端)

1)客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。
2)连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream(), getOutputStream()获取即可。
3)与服务端通讯结束后,关闭Socket。

☆基本思路(服务器端)

1)服务端需要明确它要处理的数据是从哪个端口进入的。
2)当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。
3)当该客户端访问结束,关闭该客户端。

 

 

☆客户端

通过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();

☆TCP传输最容易出现的问题
1)客户端连接上服务端,两端都在等待,没有任何数据传输。
a通过例程分析:
  1)因为read方法或者readLine方法是阻塞式。
b解决办法:
  1)自定义结束标记
  2)使用shutdownInput,shutdownOutput方法。

实战项目:

☆上传图片文件

客户端需求:把一个图片文件发送到服务端并读取回馈信息。要求判断文件是否存在及格式是否为jpg或gif并要求文件小于2M。
服务端需求:接收客户端发送过来的图片数据。进行存储后,回馈一个 上传成功字样。支持多用户的并发访问。

 

服务器端:

package cn.hucu.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;

public class uploadPicFileServer {
// main线程只负责握手
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(10006);
while (true) {
Socket s = server.accept();
new Thread(new UploadThread(s)).start();
}
}
}
class UploadThread implements Runnable {
private Socket s;
private BufferedInputStream bis; //用户信息对象
private BufferedOutputStream bos;
private OutputStream out; // 反馈给用户的流对象
public UploadThread(Socket s) {
this.s = s;
}
@Override
public void run() {
String ip = s.getInetAddress().getHostAddress(); //获取对方IP
System.out.println(ip + "connected.....");
// 接收文件上传 :流拷贝
// 1源 :socket InputStraem
try {
bis = new BufferedInputStream(s.getInputStream());
// 服务器端文件名的取法:ip.jpg,ip(1).jpg,ip(2).jpg,ip(3).jpg.....
File dir = new File("upload/pics");
/**
* 判断文件是否存在,如果没有,则创建一个文件
*/
if (!dir.exists()) {
dir.mkdir();
}
int count = 1;
File file = new File(dir, ip + ".jpg");
if (file.exists()) {
file = new File(dir, ip + "(" + (count++) + ")" + ".jpg");
}
// 经过前面的防护,此时的file
// 2目的 FileInputStream
bos = new BufferedOutputStream(new FileOutputStream(file));
// 3while对拷
byte buf[] = new byte[1024];
int len = 0;
while ((len = bis.read(buf)) != -1) {
bos.write(buf, 0, len);
}
/**
* 给客户端反馈提示信息
*/
OutputStream out = s.getOutputStream();
out.write("图片上传成功!".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
throw new RuntimeException("关流失败!!");
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
throw new RuntimeException("关流失败!!");
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
throw new RuntimeException("关流失败!!");
}
}
try {
s.close();
} catch (IOException e) {
throw new RuntimeException("关流失败!!");
}
}
}
}

客服端:

package cn.hucu.TCP.uploadPicFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

public class uploadPicFileClient {
public static void main(String[] args) {
try {
//让用户选择图片并进行格式校验
JFileChooser jfc = new JFileChooser();
int res = jfc.showOpenDialog(null);
if(res!=JFileChooser.APPROVE_OPTION){
return ;
}
File file = jfc.getSelectedFile();

if(file.length()>1024*1024*2){
JOptionPane.showMessageDialog(null, "文件太大,不能超过2M!");
return;
}
if(!(file.getName().endsWith(".jpg")||file.getName().endsWith(".jpg"))){
JOptionPane.showMessageDialog(null, "文件格式错误,要求必须是jpg或gif!");
return;
}
Socket s =new Socket("127.0.0.1",10006);
//流拷贝: FileXXX --> Socket
//1源
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
//2目的
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
//3while()拷贝
byte buf[] = new byte[1024];
int len=0;
while( (len=bis.read(buf))!=-1 ){
bos.write(buf, 0, len);
}
bos.flush();//bug:虽然是字节流,但因为是缓存流(里面带缓存),所以要手动刷缓存
//告诉服务器,图片文件上传完毕
s.shutdownOutput();//Socket里面判断文件结束的标记
//接受服务器的反馈信息
InputStream in = s.getInputStream();
byte bs[] = new byte[1024];
int len2 = in.read(bs);
String info = new String(bs,0,len2);
System.out.println("服务器应答:"+info);
//关流
bis.close();
bos.close();
in.close();
s.close();
} catch (IOException e) {
throw new RuntimeException("文件失败!");
}

}
}

项目实战(二):

☆上传文本文件:读取一个本地文本文件,将数据发送到服务端,服务器端对数据进行存储。 存储完毕后,给客户端一个提示。

服务器端:

package cn.hucu.TCP.uploadTxetFile;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JOptionPane;

public class uploadTextFileServer {
public static void main(String[] args) {
ServerSocket server = null;
Socket s = null;
BufferedReader br = null;
PrintWriter pw = null;
PrintWriter out = null;
try {
server = new ServerSocket(10005);
s = server.accept();
// 1 接收客户端上传的文件并存储到磁盘
// 源: Socket---> s.getInputStream --InputStream
// 目的: 磁盘 ---> FileWriter
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
pw = new PrintWriter(new FileWriter("upload/server.txt"));
String str = "";
while ((str = br.readLine()) != null) {
if ("$^^%^&".equals(str)) { // 自定义结束标记
break;
}
pw.println(str);
}
// 回馈给用户发送成功
out = new PrintWriter(s.getOutputStream(), true);// 自动刷缓冲
out.write("上传成功!!!");

} catch (IOException e) {
JOptionPane.showMessageDialog(null, "文件上传失败!!");
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
throw new RuntimeException("缓冲流关闭失败!!!");
}
}
if (pw != null) {
pw.close();
}
if (out != null) {
out.close();
}
if (s != null) {
try {
s.close();
} catch (IOException e) {
throw new RuntimeException("Socket流关闭失败!!!");
}
}
}
}
}

客户端:

 

package cn.hucu.TCP.uploadTxetFile;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class uploadTextFileClient {
public static void main(String[] args) {
Socket s = null;
BufferedReader br = null;
BufferedReader br2 = null;
PrintWriter pw = null;
try {
s = new Socket("127.0.0.1", 10005);
// 1上传文件
// 源: 磁盘文件 ---FileReader
// 目的:socket ---s.getOutputStream --> OutputStream
br = new BufferedReader(new FileReader("upload/blog.txt"));
pw = new PrintWriter(s.getOutputStream(), true);
String str = "";
while ((str = br.readLine()) != null) {
pw.println(str);
}
// pw.println("$^^%^&");自定义结束标记
s.shutdownOutput();

// 2接收服务器的反馈信息(上传成功的提示)
br2 = new BufferedReader(new InputStreamReader(s.getInputStream()));
String str2 = null;
while ((str2 = br2.readLine()) != null) { // 如果回馈信息较大,
System.out.println(str2);
}

} catch (IOException e) {
e.printStackTrace();
} finally {
if (s != null) {
try {
s.close();
} catch (IOException e) {
throw new RuntimeException("Socket流关闭失败!");
}
}
if (br != null) {
try {
br.close();
} catch (IOException e) {
throw new RuntimeException("打印流关闭失败!");
}
}
if (br2 != null) {
try {
br2.close();
} catch (IOException e) {
throw new RuntimeException("打印流关闭失败!");
}
}
if (pw != null) {
try {
pw.close();
} catch (Exception e) {
throw new RuntimeException("文件流关闭失败!");
}
}

}
}
}

 

  

 

举报

相关推荐

0 条评论