Java Socket和ServerSocket 网络编程
转载请注明出处:http://blog.csdn.net/u012891600/article/details/52444146
在java和android面试中我们经常会被问起Socket编程,那么什么才是Socket?
- 什么才是Socket?
- 两个应用程序可以通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个Socket
- Socket可以看成在两个程序进行通讯连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将
这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。 - Socket通常用来实现client-server连接,建立连接时所需的寻址信息为远程计算机的IP地址和端口号(Port Number)
- Socket的通讯过程
public class TestClientSocket {
public static void main(String[] args) {
try {
//第一步 创建Socket对象
Socket s = new Socket("localhost",8888);
//子线程实现通讯
new Thread(new saveFile(s)).start();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class saveFile implements Runnable{
private Socket s;
public saveFile(Socket s) {
super();
this.s = s;
}
@Override
public void run() {
ObjectInputStream oos;
BufferedOutputStream bos =null;
try {
//第二步连接到Socket的输入/输出流
oos = new ObjectInputStream(s.getInputStream());
String fileName = oos.readUTF();
long fileLength = oos.readLong();
System.out.println("文件名:"+fileName+" 长度:"+fileLength);
File file = new File("/Users/dpb/Desktop/save/"+fileName);
while(file.exists()){
file = new File("/Users/dpb/Desktop/save/"+"1"+file.getName());
}
bos = new BufferedOutputStream(new FileOutputStream(file));
byte b[] = new byte[1024];
int sum = 0 ; //已经读取的长度
int num = 0 ;
//3.按照一定的协议对socket进行读/写操作;
while(sum < fileLength){
if(sum+1024 > fileLength){
num = oos.read(b,0,(int)(fileLength-sum));
}else{
num = oos.read(b);
}
sum += num;
bos.write(b, 0, num);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
//4.关闭流;
bos.close();
System.out.println("数据下载完成....");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
3.掌握TCP Socket 通信模型
1.通信原理
2.通信模型
3.网络传输中注意事项
服务器读取网络上的远程数据时不应该以读到-1作为结束,应该用先前客户端告知的文件大小与
累计接收到的数据大小比较来判断循环是否应该结束.
客户端关闭流会让服务器读到-1,如果客户端在上传完文件后还要给服务器发其他信息,服务器就不
能结束循环了,直到客户端close掉输出流
关闭任何关联到Socket上的流,都会将Socket自动关闭掉;
关闭Socket将会自动关闭关联在上面的流.
关闭高级流会递归的关闭它包装的低级流.
4.服务器端多线程向多客户端写文件
ServerFile
等待新连接的客户端,启动线程向客户端写出指定文件
FileThread
线程类, ObjectOutputStream:writeLong()告知客户端文件大小,
OutputStream:write()向客户端写文件
ClientFile
从线程类对象获知文件大小ObjectInputStream:readLong(),
读线程类对象发过来的文件数据,并写出到本地文件中*服务端编程
public class TestServerSocket {public static void main(String[] args) {
try {
//建立服务端socket对象
ServerSocket ss = new ServerSocket(8888);
while(true){
Socket s = ss.accept(); //阻塞事件
System.out.println(s.getInetAddress().getHostName()+”连接了,准备下载数据…”);
new Thread(new FileThread(s)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
}
/**
* 服务端 把资源写入Socket
* @author dpb
*
*/
class FileThread implements Runnable{
private Socket s;
public FileThread(Socket s) {
super();
this.s = s;
}
@Override
public void run() {
BufferedInputStream bis = null;
File file = new File("/Users/dpb/Desktop/作业.zip");
ObjectOutputStream oos = null;
try {
bis = new BufferedInputStream(new FileInputStream(file));
oos = new ObjectOutputStream(s.getOutputStream());
oos.writeUTF(file.getName());
oos.writeLong(file.length());
byte b[] = new byte[1024];
int num = 0;
while((num = bis.read(b)) != -1){
oos.write(b,0,num);
}
oos.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- *通信的三种方式
方式一
OutputStream(write())
InputStream(read())
方式二
BufferedWriter(write(),注意newLine(),flush()) PrintWriter(println())
BufferedReader(readLine())
方式三
ObjectInputStream(readObject())
ObjectOutputStream(writeObject())