您的位置:首页 > 理论基础 > 计算机网络

传统tcp网络编程入门示例

2017-04-05 22:25 573 查看
1.demo

public class Server {
public static void main(String[] args) throws IOException {
// 创建一个ServerSocket,用于监听客户端Socket的连接请求
ServerSocket ss = new ServerSocket(30000);
// 采用循环不断接受来自客户端的请求
while (true) {
// 每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
Socket s = ss.accept();
// 方式一
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("hello,您收到了服务器的问候!");// 进行普通IO操作
ps.close();
s.close();
// 方式二
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write("hello,您收到了服务器的问候!\n");// 必须同时加上\n和flush,客户端用readLine才能输出
bw.flush();
// 方式三
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println("来自客户端的数据:" + br.readLine());
}
}
}

public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 30000);
// 方式一、二
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = br.readLine();
System.out.println("来自服务器的数据:" + line);
br.close();
socket.close();
// 方式三
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("hello,您收到了客户端的问候!");// 只需要加flush,服务器端用readLine就能输出
bw.flush();
}
}
2.半关闭的Socket

public class Server {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(30000);
Socket socket = ss.accept();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("服务器的第一行数据");
ps.println("服务器的第二行数据");
// 关闭socket的输出流,表明输出数据已经结束
socket.shutdownOutput();
// 下面语句将输出false,表明socket还未关闭。
System.out.println(socket.isClosed());
Scanner scan = new Scanner(socket.getInputStream());
while (scan.hasNextLine()) {
System.out.println(scan.nextLine());
}
scan.close();
socket.close();
ss.close();
}
}

public class Client {
public static void main(String[] args) throws Exception {
Socket s = new Socket("localhost", 30000);
Scanner scan = new Scanner(s.getInputStream());
while (scan.hasNextLine()) {
System.out.println(scan.nextLine());
}
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("客户端的第一行数据");
ps.println("客户端的第二行数据");
ps.close();
scan.close();
s.close();
}
}

3.ByteArrayOutputStream

PrintStream的write方法是可以用的,只不过要在后面加上输出\n,否则就用它的println,否则因为接收端用的是nextLine()会因为没有末尾的换行

而读取不到数据;但用字节的方式接收的话就不必关心末尾有没有\n了

public class Server {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(30000);
while (true) {
Socket socket = server.accept();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.write("这是测试么?".getBytes());
ps.println("这是测试么??");
ps.print("这是测试么??");
socket.shutdownOutput();// 必须关闭,否则客户端会阻塞在read方法上
}
}

}

public class Client {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 30000);
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
ByteArrayOutputStream bout = new ByteArrayOutputStream();
int len;
while (true) {
len = is.read(bytes);
System.out.println("len = " + len);
if (len < 0) {
break;
}
bout.write(bytes, 0, len);
}
System.out.println(bout.size());
System.out.println(bout.toString());
}
}
4.多线程

public class MyServer {
// 定义保存所有Socket的ArrayList,并将其包装为线程安全的
public static List<Socket> socketList = Collections.synchronizedList(new ArrayList<Socket>());

public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(30000);
while (true) {
// 此行代码会阻塞,将一直等待别人的连接
Socket s = ss.accept();
socketList.add(s);
// 每当客户端连接后启动一条ServerThread线程为该客户端服务
new Thread(new ServerThread(s)).start();
}
}
}

// 负责处理每个线程通信的线程类
public class ServerThread implements Runnable {
// 定义当前线程所处理的Socket
Socket s = null;
// 该线程所处理的Socket所对应的输入流
BufferedReader br = null;

public ServerThread(Socket s) throws IOException {
this.s = s;
// 初始化该Socket对应的输入流
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}

public void run() {
try {
String content = null;
// 采用循环不断从Socket中读取客户端发送过来的数据
while ((content = readFromClient()) != null) {
// 遍历socketList中的每个Socket,
// 将读到的内容向每个Socket发送一次
for (Socket s : MyServer.socketList) {
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println(content);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}

// 定义读取客户端数据的方法
private String readFromClient() {
try {
return br.readLine();
}
// 如果捕捉到异常,表明该Socket对应的客户端已经关闭
catch (IOException e) {
// 删除该Socket。
MyServer.socketList.remove(s); // ①
}
return null;
}
}

public class MyClient {
public static void main(String[] args) throws Exception {
Socket s = new Socket("127.0.0.1", 30000);
// 客户端启动ClientThread线程不断读取来自服务器的数据
new Thread(new ClientThread(s)).start(); // ①
// 获取该Socket对应的输出流
PrintStream ps = new PrintStream(s.getOutputStream());
String line = null;
// 不断读取键盘输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while ((line = br.readLine()) != null) {
// 将用户的键盘输入内容写入Socket对应的输出流
ps.println(line);
}
}
}

public class ClientThread implements Runnable {
// 该线程负责处理的Socket
private Socket s;
// 该线程所处理的Socket所对应的输入流
BufferedReader br = null;

public ClientThread(Socket s) throws IOException {
this.s = s;
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}

public void run() {
try {
String content = null;
// 不断读取Socket输入流中的内容,并将这些内容打印输出
while ((content = br.readLine()) != null) {
System.out.println(content);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
参考:

疯狂java讲义
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: