1、服务器端获取客服端传来的数据:
直接在eclipse中新建一个Server类:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String args[]) throws IOException {
int port = 8899;
//定义一个ServerSocket监听在端口8899上
ServerSocket server = new ServerSocket(port);
//server尝试接收客户端Socket的连接请求,server的accept方法是阻塞式的
Socket socket = server.accept();
//读取客户端发过来的信息
Reader reader = new InputStreamReader(socket.getInputStream());
char chars[] = new char[64];
int len;
StringBuilder sb = new StringBuilder();
while ((len=reader.read(chars)) != -1) {
sb.append(new String(chars, 0, len));
}
System.out.println("from client: " + sb);
reader.close();
socket.close();
server.close();
}
}
阻塞式:当服务器socket接收到数据才往后执行,没有收到数据就暂停在当前程序位置等待数据。
可以先执行Server的主方法,执行后,查看端口:cmd-->netstat -ano 就会发现8899端口处于监听的状态。
根据进程pid查看该端口被那个应用占用:
C:\Users\Administrator>tasklist|findstr 4844
javaw.exe 4844 Console 1 14,992 K
说明Server类的主方法并没有执行完毕。
Client类:
import java.io.*;
import java.net.*;
public class Client{
public static void main(String args[]) throws Exception {
String host = "127.0.0.1"; //要连接的服务端IP地址
int port = 8899; //要连接的服务端对应的监听端口
//与服务端建立连接
Socket client = new Socket(host, port);
//建立连接后就可以往服务端写数据了
Writer writer = new OutputStreamWriter(client.getOutputStream());
writer.write("Hello Server.");
writer.flush();//写完后要记得flush
writer.close();
client.close();
}
}
执行Client的主方法,控制台上打印:from client: Hello Server.
这时再去查看端口8899,发现端口已经被关闭,Server的主方法执行完毕。
若先执行Client主方法会是怎样?会出现Connection refused: connect
若将Client类中writer.flush();删掉会是怎样?此时还是能读取到from client: Hello Server.
2、客服端、服务器同时读写数据:
每次数据写入时 添加结束标记:"eof";发现端口8899开启过多可以先关闭eclipse或javaw.exe,确保每次运行Server之前8899端口是关闭的。
Server:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String args[]) throws IOException {
int port = 8899;
ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
Reader reader = new InputStreamReader(socket.getInputStream());
char chars[] = new char[64];
int len;
StringBuilder sb = new StringBuilder();
String temp;
int index;
while ((len=reader.read(chars)) != -1) {
temp = new String(chars, 0, len);
if ((index = temp.indexOf("eof")) != -1) {//遇到eof时就结束接收
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
System.out.println("from client: " + sb);
//读完后写一句
Writer writer = new OutputStreamWriter(socket.getOutputStream());
writer.write("Hello Client32.eof3232"); //出现eof表示输入结束
writer.flush();
writer.close();
reader.close();
socket.close();
server.close();
}
}
Client类:
import java.io.*;
import java.net.*;
public class Client{
public static void main(String args[]) throws Exception {
String host = "127.0.0.1"; //要连接的服务端IP地址
int port = 8899; //要连接的服务端对应的监听端口
Socket client = new Socket(host, port);
Writer writer = new OutputStreamWriter(client.getOutputStream());
writer.write("Hello Server");
writer.write("eof");
writer.flush();
Reader reader = new InputStreamReader(client.getInputStream());
char chars[] = new char[64];
int len;
StringBuffer sb = new StringBuffer();
String temp;
int index;
while ((len=reader.read(chars)) != -1) {
temp = new String(chars, 0, len);
if ((index = temp.indexOf("eof")) != -1) {
sb.append(temp.substring(0, index));
break;
}
sb.append(new String(chars, 0, len));
}
System.out.println("from server: " + sb);
reader.close();
writer.close();
client.close();
}
}
还是先执行Server主方法再执行Client主方法:
点击Console按钮切换Server/Client的打印信息:
from server: Hello Client32.
from client: Hello Server
3、多个客户端链接同一个服务器端
这才是实际需要的,还是以"eof"为结束标记;这里没有关闭端口。
Server:每次ServerSocket接收到一个新的Socket连接请求后新建一个线程来跟当前Socket进行通信,实现并发处理与客户端Socket进行通信的情况。由于现在的Server是异步处理数据的,不必一次性将客户端传来的数据读完,可以使用BufferedReader这个类,每次读取一行数据。
import java.io.*;
import java.net.*;
public class Server {
@SuppressWarnings("resource")
public static void main(String args[]) throws IOException {
int port = 8899;
ServerSocket server = new ServerSocket(port);
while (true) {
Socket socket = server.accept();
new Thread(new Task(socket)).start(); //启动Runnable接口下类的run()方法;
}
}
/**
* 用来处理Socket请求的
*/
static class Task implements Runnable {
private Socket socket;
public Task(Socket socket) {
this.socket = 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(socket.getInputStream()));
StringBuilder sb = new StringBuilder();
String temp;
int index;
while ((temp=br.readLine()) != null) {
if ((index = temp.indexOf("eof")) != -1) {//遇到eof时就结束接收
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
System.out.println("from client: " + sb);
//读完后写一句
Writer writer = new OutputStreamWriter(socket.getOutputStream());
writer.write("Hello Client.");
writer.write("eof");
writer.flush();
writer.close();
br.close();
socket.close();
}
}
}
可以用线程实例多个Client对象模拟并发访问Server,这里就不实现了(也可以创建2个Client类简单模拟下)。
import java.io.*;
import java.net.*;
public class Client{
public static void main(String args[]) throws Exception {
String host = "127.0.0.1"; //要连接的服务端IP地址
int port = 8899; //要连接的服务端对应的监听端口
Socket client = new Socket(host, port);
Writer writer = new OutputStreamWriter(client.getOutputStream());
writer.write("Hello Server first\n");
writer.write("Hello Server second\n");
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")) >0) {
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
System.out.println("from server: " + sb);
writer.close();
br.close();
client.close();
}
}
设置编码:BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
Writer writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
设置阻塞超时中断连接(一般设置在客户端),Socket提供setSoTimeout()方法来设置接收数据的超时时间,单位是毫秒,抛出SocketTimeoutException。
在server中添加:
Thread.sleep(5000);
// writer.flush();
Client:
import java.io.*;
import java.net.*;
public class Client{
public static void main(String args[]) throws Exception {
String host = "127.0.0.1"; //要连接的服务端IP地址
int port = 8899; //要连接的服务端对应的监听端口
Socket client = new Socket(host, port);
Writer writer = new OutputStreamWriter(client.getOutputStream());
writer.write("Hello Server 我的\n");
writer.write("Hello Server second\n");
writer.write("eof\n");
writer.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
client.setSoTimeout(2000);
StringBuffer sb = new StringBuffer();
try{
String temp;
int index;
while ((temp=br.readLine()) != null) {
if ((index = temp.indexOf("eof")) >0) {
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
}catch(SocketTimeoutException e){
System.out.println("数据读取超时。");
}
System.out.println("from server: " + sb);
writer.close();
br.close();
client.close();
}
}
客服端就会打印超时;可能出现的异常 Address already in use: JVM_Bind
最好用netstat -ano查看后、决定是否关闭相应进程或修改端口。
一般解决办法:
1、修改程序端口
2、重启eclipse或javaw.exe