Java学习笔记--Socket和ServerSocket
参考资料:
http://haohaoxuexi.iteye.com/blog/1979837
http://zhidao.baidu.com/link?url=OeOSa0YbOzSbMVPa8sgPXcwtyyHsWB1lPkh1XopETtNK_lVtbd9lL7NH3qlFxjC-4kNUmCkIXgcfRW7KJq9_FK
http://www.cnblogs.com/rond/p/3565113.html
http://www.cnblogs.com/mengdd/archive/2013/03/10/2952616.html
TCP/IP客户套接字
Java中有两种类型的TCP套接字,一种用于服务器,一种用于客户端。
ServerSocket类型设计成“监听器”,等待客户端连接的到来。因此,ServerSocket用于服务器。
Socket类用于客户端,它被设计成连接服务器套接字并且初始化协议的交换。
图片来自:http://www.cnblogs.com/rond/p/3565113.html
Socket
Socket可以使客户程序与服务器程序通信,使用Socket连接服务器的过程包含以下4个基本的步骤
(1)创建Socket
(2)打开连接到Socket的输入/输出流
(3)按照一定协议对Socket执行读写操作
(4)关闭Socket
Socket()
boolean isConnection=socket.isConnected() && !socket.isClosed(); //判断当前是否处于连接
半关闭Socket
- 自定义标识符(譬如下面的例子,当受到“bye”字符串的时候,关闭Socket)
- 告知读取长度(有些自定义协议的,固定前几个字节表示读取的长度的)
- 读完所有数据
- 当Socket调用close的时候关闭的时候,关闭其输入输出流
例:
public class TestPort {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String hostname = "www.baidu.com";
InetAddress addr = InetAddress.getByName(hostname);
Socket so = new Socket(addr,80);
System.out.println("远程连接地址:"+so.getInetAddress());
System.out.println("远程连接端口:"+so.getPort());
System.out.println("本地连接地址:"+so.getLocalAddress());
System.out.println("本地连接端口:"+so.getLocalPort());
InputStream is = so.getInputStream();
/*
* 这部分为客户端操作,需要一台远程服务器
int c;
while((c=is.read())!=-1){
System.out.println("gas");
}*/
is.close();
so.close();
}
}
运行结果:
远程连接地址:www.baidu.com/119.75.218.70
远程连接端口:80
本地连接地址:/192.168.1.160
本地连接端口:4338
public class GetServerIP {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
InetAddress addr =InetAddress.getByName("localhost");
ServerSocket se = new ServerSocket(10000,10,addr);
System.out.println(se.getInetAddress());
System.out.println(se.getLocalPort());
}
}
运行结果
localhost/127.0.0.1
10000
附:完整例子
发送端 socket
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket; public class SocketSender {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 27401);
// 向服务端发送信息
OutputStream outer = socket.getOutputStream();
byte[] b = "客户端:向服务端发送文字,\"这是一行测试....\"".getBytes();
outer.write(b);
outer.flush();
System.out.println("发送完毕!"); // 接收服务端的返回值
InputStream inner = socket.getInputStream();
int count = 0;
while (count == 0) {
count = inner.available();
}
byte[] recv = new byte[count];
inner.read(recv); String str_recv = new String(recv);
System.out.println("客户端:接收到服务端的文字:" + str_recv);
} catch (IOException e) {
System.out.println("发送端出现异常");
} finally {
if (socket != null)
try {
socket.close();
} catch (IOException e) {
System.out.println("发送端 finally 出现异常");
}
}
}
}
接收端:ServerSocket
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket; public class SocketReceiver {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(27401);
while (true) {
Socket socket = serverSocket.accept(); // 接收客户端的信息
InputStream in = socket.getInputStream();
int count = 0;
while (count == 0) {
count = in.available();
}
byte[] b = new byte[count];
in.read(b);
String str = new String(b);
System.out.println(str); // 向客户端发送确认消息
OutputStream outer = socket.getOutputStream();
byte[] b_out = "已经收到,返回消息码200".getBytes();
outer.write(b_out);
outer.flush(); // 关闭socket
socket.close();
}
} catch (IOException e) {
System.out.println("接收端出现异常");
} finally {
if (serverSocket != null)
try {
serverSocket.close();
} catch (IOException e) {
System.out.println("接收端 finally 出现异常");
}
}
}
}
接收端:方法2,利用多线程,每一个发送端对应接收端的一个线程
public class SocketReceiverWithThread {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(27401);
while (true) {
Socket socket = serverSocket.accept();
new Thread(new Handler(socket)).start();
//socket.close(); 注意 关闭socket不能在这里,而应该写在线程内,否则可能线程没结束就关闭了socket
} } catch (IOException e) {
System.out.println("接收端出现异常");
} finally {
if (serverSocket != null)
try {
serverSocket.close();
} catch (IOException e) {
System.out.println("接收端 finally 出现异常");
}
}
}
} class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
// 接收客户端的信息
InputStream in = socket.getInputStream();
int count = 0;
while (count == 0) {
count = in.available();
}
byte[] b = new byte[count];
in.read(b);
String str = new String(b);
System.out.println(str); // 向客户端发送确认消息
OutputStream outer = socket.getOutputStream();
byte[] b_out = "已经收到,返回消息码200".getBytes();
outer.write(b_out);
outer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭socket
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
附2:使用socket进行文件传送
客户端 ClienPart.java
package com.client; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket; public class ClientPart {
private Socket socket=null;
private String ip ;// 设置成服务器IP
private int port ; public ClientPart(String ip,int port) {
this.ip=ip;
this.port=port; }
private boolean createConnection() {
try {
socket = new Socket(ip, port);
System.out.print("连接服务器成功!" + "\n");
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//向服务器发送消息
private void sentMessage(String msg){
if (socket == null)
return;
Writer writer;
try {
writer = new OutputStreamWriter(socket.getOutputStream());
writer.write(msg);
writer.flush(); //写完后要记得flush
writer.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void getFile() {
if (socket == null)
return;
DataInputStream inputStream = null;
try {
inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
} catch (Exception e) {
System.out.print("接收消息缓存错误\n");
return;
}
try {
//本地保存路径,文件名会自动从服务器端继承而来。
String savePath = "F:\\client\\";
int bufferSize = 8192;
byte[] buf = new byte[bufferSize];
long len=0; savePath += inputStream.readUTF(); //读取文件名
DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(savePath))));
len = inputStream.readLong(); //读取文件长度 System.out.println("文件的长度为:" + len);
System.out.println("开始接收文件!"); while (true) {
int read = 0;
if (inputStream != null) {
read = inputStream.read(buf);
}
if (read == -1) {
break;
}
//客户端读出文件
fileOut.write(buf, 0, read);
} System.out.println("接收完成,文件存为" + savePath + "\n");
fileOut.close();
socket.close();
} catch (Exception e) {
System.out.println("接收消息错误" + "\n");
return;
}
} private void putFile(String filename){
String filePath = filename;
File client_file = new File(filePath); //要传输的文件路径
long filelen = client_file.length();
System.out.println("要上传的文件长度:" + (int)filelen);
try{
DataInputStream in_stream = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
DataOutputStream out_stream = new DataOutputStream(socket.getOutputStream());
out_stream.writeUTF(client_file.getName());
out_stream.flush();
out_stream.writeLong((long) client_file.length());
out_stream.flush(); int bufferSize = 8192;
byte[] buf = new byte[bufferSize]; while (true) {
int read = 0;
if (in_stream != null) {
read = in_stream.read(buf);
}
if (read == -1) {
break;
}
out_stream.write(buf, 0, read);
}
out_stream.flush();
// 注意关闭socket链接,不然客户端会等待server的数据过来,
// 直到socket超时,会导致数据不完整。
in_stream.close();
socket.close();
System.out.println("文件传输完成");
}catch(Exception e){
e.printStackTrace();
} } public static void main(String arg[]) {
ClientPart client = new ClientPart("127.0.0.1",7005);
client.createConnection();
client.sentMessage("read");//向服务器发送信息,说明需要读取文件
client.createConnection();
client.getFile(); //获取服务器发送的文件 client.createConnection();
client.sentMessage("write");//向服务器发送信息,说明需要上传文件
client.createConnection();
client.putFile("F:\\client\\1.txt");//向服务器发送文件 }
}
服务端 ServerPart.java
package com.server; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket; public class ServerPart {
int port = 7005;
public void serverStart() {
try {
ServerSocket ssocket = new ServerSocket(port);
System.out.println("服务器准备完毕!");
while (true) {
String msg = checkIO(ssocket); //获取来自客户端的请求是读/写
if(msg.compareTo("read")==0){
sendFile(ssocket); //向客户端发送文件
}
else if(msg.compareTo("write")==0){
saveFile(ssocket); //存储来自客户端的文件
}
}
} catch (Exception e) {
e.printStackTrace();
}
} //服务器检查来自客户端的请求是读/写
public String checkIO(ServerSocket ssocket) throws IOException{
Socket socket=ssocket.accept();
Reader reader = new InputStreamReader(socket.getInputStream());
char chars[] = new char[10];
int len;
StringBuilder sb = new StringBuilder();
while ((len=reader.read(chars)) != -1) {
sb.append(new String(chars, 0, len));
}
reader.close();
socket.close();
return sb.toString();
} public void sendFile(ServerSocket ssocket) throws IOException{
Socket soc = null;
// 选择进行传输的文件
String filePath = "F:\\server\\info.bin";
File myfile = new File(filePath);
System.out.println("服务器文件长度:" + (int) myfile.length());
soc = ssocket.accept();
System.out.println("建立socket链接"); DataInputStream in_stream = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
DataOutputStream out_stream = new DataOutputStream(soc.getOutputStream());
//将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,具体可以参见Think In Java 4th里有现成的代码。
out_stream.writeUTF(myfile.getName());
out_stream.flush();
out_stream.writeLong((long) myfile.length());
out_stream.flush(); int bufferSize = 8192;
byte[] buf = new byte[bufferSize]; while (true) {
int read = 0;
if (in_stream != null) {
read = in_stream.read(buf);
}
if (read == -1) {
break;
}
out_stream.write(buf, 0, read);
}
out_stream.flush();
// 注意关闭socket链接哦,不然客户端会等待server的数据过来,
// 直到socket超时,导致数据不完整。
out_stream.close();
in_stream.close();
soc.close();
System.out.println("服务器文件传输完成");
} //服务器保存文件的方法
public void saveFile(ServerSocket ssocket) throws IOException{
Socket soc = ssocket.accept();
if (soc == null)
return;
DataInputStream inputStream = null;
try {
inputStream = new DataInputStream(new BufferedInputStream(soc.getInputStream()));
} catch (Exception e) {
System.out.print("服务器接收消息缓存错误\n");
return;
} try {
//服务器文件的保存路径
String savePath = "f:\\server\\";
int bufferSize = 8192;
byte[] buf = new byte[bufferSize];
long len=0; savePath += inputStream.readUTF(); //读取文件名
DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(savePath))));
len = inputStream.readLong(); //读取文件长度
//控制台输出
System.out.println("文件的长度为:" + len);
System.out.println("开始接收文件!"); while (true) {
int read = 0;
if (inputStream != null) {
read = inputStream.read(buf);
}
if (read == -1) {
break;
}
//客户端读出文件
fileOut.write(buf, 0, read);
}
System.out.println("接收完成,文件存为" + savePath + "\n");
fileOut.close();
soc.close();
} catch (Exception e) {
System.out.println("接收消息错误" + "\n");
e.printStackTrace();
return;
}
} public static void main(String arg[]) {
//启动服务器
new ServerPart().serverStart();
}
}
Java学习笔记--Socket和ServerSocket的更多相关文章
- Java学习笔记——Socket实现文件传输
我越是逃离,却越是靠近你. 我越是背过脸,却越是看见你. 我从你开始, 我在你结束. 需求:实现局域网下socket传输文件. 客户端步骤: 1.建立与服务器的连接 2.创建client输出流 3.创 ...
- Java学习笔记4
Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...
- 20155234 2016-2017-2第十周《Java学习笔记》学习总结
20155234第十周<Java学习笔记>学习总结 教材学习内容总结 网络编程 在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置,或者接收到指定 ...
- 20145330第十周《Java学习笔记》
20145330第十周<Java学习笔记> 网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置,或者接收到指定的数据,这个就 ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- 0035 Java学习笔记-注解
什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...
- Java学习笔记(04)
Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...
- 0032 Java学习笔记-类加载机制-初步
JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...
- 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用
垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...
随机推荐
- 开发自定义View
当开发者打算派生自己的UI组件时,首先定义一个继承View基类的子类,然后重写View类的一个或多个方法,通常可以被用户重写的方法如下:构造器:重写构造器是定制View的最基本方法,当Java代码创建 ...
- Altium Designer同一个工程里不同原理图导入到不同的PCB
问题: 在用Altium Designer进行PCB工程设计时,有时一个工程里可能不止一块PCB,比如,一个设备里有主板和扩展板或者按键板等等,这时就需要在一个工程里添加多个PCB文件.如图: 我们知 ...
- 子句判断、启动强度和去模糊化--AForge.NET框架的使用(三)
原文:子句判断.启动强度和去模糊化--AForge.NET框架的使用(三) 使用AForge.NET进行模糊运算 上一篇说来一些模糊运算的数学问题,用AForge.NET做相关运算就很简单了. 1.联 ...
- Mysql 存储过程和函数区别
存储过程是procedure用户定义的一系列sql语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表. 存储 ...
- Git Bash下实现复制粘贴等快速编辑功能
在windows下使用Git Bash会经常用到选中.复制.粘贴等功能,但是一般用的方法会很复杂,笔者经过查阅一些资料,特整理一些常见编辑功能的实现方法. (1)默认方法: 单击左上角的logo ic ...
- ios 限制输入长度
----------------UITextField限制输入的长度------------ - (BOOL)textField:(UITextField *)textField shouldChan ...
- wpf下拉框不能多选的原因
<dxe:ComboBoxEdit Margin="0" Height="25" Width="65" VerticalAlignm ...
- (转)OpenSSL命令---pkcs12
用途: pkcs12文件工具,能生成和分析pkcs12文件.PKCS#12文件可以被用于多个项目,例如包含Netscape. MSIE 和 MS Outlook. 用法: openssl pkcs12 ...
- Cocos2D-X v3.0 alpha1环境搭建
周末看了下Cocos2D,感觉用起来还是挺爽的样子,跨平台,支持Windows, Linux, Mac, IOS, Android,WP...N多平台..还是C++开源滴,果断下下来研究下.. 最新版 ...
- java开发webservice的几种方式
webservice的应用已经越来越广泛了,下面介绍几种在Java体系中开发webservice的方式,相当于做个记录. 1.Axis2 Axis是apache下一个开源的webservice开发组件 ...