先前有篇博文专门写了socket的基本概念,这里用java来实现简单的server-client的socket数据传输。
server端
/**
* socket服务端
*
* @author peter_wang
* @create-time 2014-8-30 下午3:25:27
*/
public class Server {
public static void main(String args[])
throws IOException {
int port = 8888;
ServerSocket server = new ServerSocket(port);
while (true) {
// 开始接受socket请求
Socket socket = server.accept();
// 建立新线程处理新进的socket请求
new Thread(new Task(socket)).start();
}
}
/**
* 处理Socket请求的异步任务
*/
static class Task
implements Runnable {
private Socket mSocket;
public Task(Socket socket) {
this.mSocket = socket;
}
public void run() {
try {
handleSocket();
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* 跟客户端Socket进行通信
*
* @throws Exception
*/
private void handleSocket()
throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(mSocket.getInputStream(), "UTF-8"));
StringBuilder sb = new StringBuilder();
String temp;
int index;
while ((temp = br.readLine()) != null) {
// 遇到eof时结束接收
if ((index = temp.indexOf("eof")) != -1) {
System.out.println(temp);
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
System.out.println("data from client: " + sb);
// 写操作
Writer writer = new OutputStreamWriter(mSocket.getOutputStream());
writer.write("Hello Client.");
writer.write("eof\n");
writer.flush();
writer.close();
br.close();
mSocket.close();
}
}
}
client端
/**
* socket客户端
*
* @author peter_wang
* @create-time 2014-8-30 下午4:13:11
*/
public class Client {
public static void main(String args[])
throws Exception {
String host = "127.0.0.1"; // 本地地址
int port = 8888;
// 与服务端建立连接
Socket client = new Socket(host, port);
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
System.out.println("输入的内容为:" + str);
// 建立连接后就可以往服务端写数据了
Writer writer = new OutputStreamWriter(client.getOutputStream(), "UTF-8");
writer.write(str);
writer.write("eof\n");
writer.flush();
// 写完以后进行读操作
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
StringBuffer sb = new StringBuffer();
String temp;
int index;
while ((temp = br.readLine()) != null) {
if ((index = temp.indexOf("eof")) != -1) {
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
System.out.println("from server: " + sb);
writer.close();
br.close();
client.close();
}
}
1.用了eof做完读写结束标识。
2.BufferedReader提高了IO效率,用异步提前准备好数据存储到内存,读取直接从内存读,如果数据来源于磁盘IO或网络IO,速度将快很多,磁盘读取和内存读取的速度对比参见这篇文章。
3.server和client之间数据传输需要统一编码,防止乱码。
4.源码分析,server端的new ServerSocket(port)实现了new socket、bind、listener功能
public void bind(SocketAddress endpoint, int backlog) throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!oldImpl && isBound())
throw new SocketException("Already bound");
if (endpoint == null)
endpoint = new InetSocketAddress(0);
if (!(endpoint instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
InetSocketAddress epoint = (InetSocketAddress) endpoint;
if (epoint.isUnresolved())
throw new SocketException("Unresolved address");
if (backlog < 1)
backlog = 50;
try {
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkListen(epoint.getPort());
getImpl().bind(epoint.getAddress(), epoint.getPort());
getImpl().listen(backlog);
bound = true;
} catch(SecurityException e) {
bound = false;
throw e;
} catch(IOException e) {
bound = false;
throw e;
}
}
client端的new Socket(host, port)实现了new socket和connect功能
private Socket(SocketAddress address, SocketAddress localAddr,
boolean stream) throws IOException {
setImpl();
// backward compatibility
if (address == null)
throw new NullPointerException();
try {
createImpl(stream);
if (localAddr != null)
bind(localAddr);
if (address != null)
connect(address);
} catch (IOException e) {
close();
throw e;
}
}