练习一、模拟账户登入界面
服务端:
package Exercise;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class LoginTCPServer {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10008);
while(true){
Socket s = ss.accept();
new Thread(new User(s)).start();
}
}
}
class User implements Runnable{
private Socket s;
public User(Socket s) {
this.s = s;
}
public void run() {
try {
String id = s.getInetAddress().getHostName();
System.out.println(id + "------------connected");
//服务端口的连接可以放在循环外
BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pwOut = new PrintWriter(s.getOutputStream(),true);
BufferedReader brFile = null;
for(int i = 0; i < 3; i++){
//读取文件的输入流必须每次重新创建,因为上次的输入已经读到末尾,如果不重建,读到的文件将为空
brFile = new BufferedReader(new FileReader("LoginTCPDemo.txt"));
String name = brIn.readLine();
if(name == null)
break;
String line = null;
boolean flag = false;
while ((line = brFile.readLine()) != null) {
if(line.equals(name)){
flag = true;
break;
}
}
if(flag){
System.out.println(name + ": 已经登入");
pwOut.println("欢迎光临");
break;
}
else {
System.out.println(name + ": 尝试登入");
pwOut.println("该用户不存在");
}
}
System.out.println(id + "server--------close");
s.close();
} catch (Exception e) {
throw new RuntimeException("校验失败");
}
}
}
客户端:
package Exercise;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/*
练习:
客户端通过键盘输入用户名,服务端对这个用户名进行校验。
如果该用户名存在,在服务端显示xxx,已登入,并在用户端显示xxx,欢迎光临
如果该用户不存在,在服务端显示xxx,尝试登入,并在客户端显示xxx,该用户不存在
最多就登入三次。
*/
public class LoginTCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("192.168.188.1",10008);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pwOut = new PrintWriter(s.getOutputStream(),true);
BufferedReader bfIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
for(int i = 0; i < 3 ; i++){
String name = br.readLine();
if(name == null)
break;
pwOut.println(name);
String line = bfIn.readLine();
System.out.println(name + ":" + line);
if(line.contains("欢迎"))
break;
}
br.close();
s.close();
}
}
练习二、上传图片到网络:
服务端:
package Exercise;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
/*
服务端:
这个服务端有个局限性,当A客户端连接上以后,被服务端获取到,
服务端执行具体流程,这时B客户端连接,只能等待。
因为服务端还没有处理完A客户端的请求,还有循环回来执行下次
accept方法,所以暂时获取不到B客户端对象。
那么为了可以让多个客户端同时并发访问服务端,服务端最好就是
将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个
客户端请求。
如何定义线程:
只要明确了每个客户端要在服务端执行的代码即可,将该代码存入
run方法中。
*/
public class PicTCPServer {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10007);
while(true){
Socket s = ss.accept();
new Thread(new PicThread(s)).start();
}
}
}
class PicThread implements Runnable{
private Socket s;
public PicThread(Socket s) {
this.s = s;
}
public void run() {
int count = 1;
String id = s.getInetAddress().getHostName();
try {
System.out.println(id + "-----------connected");
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
File file = new File(id + ".jpg");
while(file.exists())
file = new File(id + "(" + (count++) + ").jpg");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] buf = new byte[1024];
int len = 0;
System.out.println("Serve------1");
while ((len = bis.read(buf)) != -1) {
bos.write(buf,0,len);
bos.flush();
}
System.out.println("Serve------2");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write("图片上传成功");
System.out.println("Serve------3");
bw.close();//关闭资源很重要,如果不关闭,提醒信息还在缓冲区,没有发送出去,客户端将出现异常
bos.close();
} catch (Exception e) {
throw new RuntimeException(id + "上传失败");
}
}
}
/*
public class PicTCPServer {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10007);
Socket s = ss.accept();
String id = s.getInetAddress().getHostName();
System.out.println(id + "-----------connected");
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.jpg"));
byte[] buf = new byte[1024];
int len = 0;
System.out.println("Serve------1");
while ((len = bis.read(buf)) != -1) {
bos.write(buf,0,len);
bos.flush();
}
System.out.println("Serve------2");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write("图片上传成功");
System.out.println("Serve------3");
bw.close();//关闭资源很重要,如果不关闭,提醒信息还在缓冲区,没有发送出去,客户端将出现异常
bos.close();
ss.close();
}
}
*/
客户端:
package Exercise;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
/*
目的:上传一张图片
客户端:
步骤:
1、建立服务端点。
2、读取客户端已有的图片数据
3、通过Socket输出流将数据发送给服务端
4、读取服务端的反馈信息。
5、关闭资源
*/
public class PicTCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("192.168.188.1",10007);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.jpg"));
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
byte[] buf = new byte[1024];
System.out.println("Client--------0");
while ((bis.read(buf)) != -1) {
bos.write(buf,0,buf.length);
bos.flush();
}
//告诉服务端数据已经写完
s.shutdownOutput();
System.out.println("Client--------1");
BufferedReader b = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(b.readLine());
System.out.println("Client--------3");
bis.close();
s.close();
}
}
练习三、上传文件到网络:
服务端:
package Exercise;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
//练习:将文件上传至服务端,并返回是否上传成功。
public class TestServer {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10006);
Socket s = ss.accept();
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw = new PrintWriter(new FileWriter("TextTCP.txt"),true);
String line = null;
while ((line = bufIn.readLine()) != null) {
pw.println(line);
}
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write("上传成功");
bw.close();
pw.close();
s.close();
ss.close();
}
}
客户端:
package Exercise;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TextClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("192.168.188.1",10006);
BufferedReader buf = new BufferedReader(new FileReader("ChatDemo.java"));
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
String line = null;
while ((line = buf.readLine()) != null) {
pw.println(line);
}
s.shutdownOutput();//客服端输出流结束,用于提醒服务端结束接收,防止等待输入,进入阻塞
BufferedReader b = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(b.readLine());
buf.close();
b.close();
s.close();
}
}
练习四、通过网络进行文本转换:
服务端:
package Exercise;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
/*
需求:
建立一个文本转换服务器,客服端给服务端发送文本,服务端会将文本转成大写再返回给客服端。
而且客服端可以不断的进行文本转换,当客服端输入over时,转换结束。
分析:服务端:
源:Socket读取流
目的:Socket输出流
都是文本,装饰下。
出现现象:
客服端和服务端都在莫名的等待,这是为什么呢?
因为客服端和服务端都有阻塞式方法,这些方法没有读取到结束标记,那么就一直等
而导致两端都在等待。
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
//建立服务端
ServerSocket ss = new ServerSocket(10005);
Socket s = ss.accept();//接收连接端口
//测试是否连接成功
String id = s.getInetAddress().getHostName();
System.out.println(id + "..............connected");
//建立网络输入流
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
//建立网络输出流
BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
//循环获取数据
while ((line = bufIn.readLine()) != null) {
System.out.println(line);
//注:不用判断结束语句,如果客服端循环结束关闭后,该循环也会自动结束
bufOut.write(line.toUpperCase());//将获取的数据转换成大写并返回
//添加换行符,不会导致获取数据的一方读完一行后因为没有读到换行符而认为读取数据未结束,而一直处于等待中
bufOut.newLine();
bufOut.flush();//读取的数据都存放于缓冲区,必须刷新后才能将数据发送出去
}
ss.close();//关闭服务端
}
}
客户端:
package Exercise;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/*
分析:客服端:
既然是操作设备上的数据,那么就可以使用IO技术,并按照IO的操作规律来思考
源:键盘录入
目的:网络输出流,而且操作的是文本数据,可以选择字符流
步骤:
1、建立服务
2、获取键盘录入
3、将数据发给服务端
4、获取服务端返回的大写数据
5、结束,关闭资源
都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲。
*/
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//建立端口服务
Socket s = new Socket("192.168.188.1",10005);
//获取键盘输入
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
//建立网络输出流
BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//建立网络输入流
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
//键盘读取数据,并将数据发送出去,然后接收返回数据
while ((line = buf.readLine()) != null) {
if("over".equals(line))
break;
//System.out.println(line);
bufOut.write(line);//读取的数据以换行符接收,但不包括换行符
//添加换行符,不会导致获取数据的一方读完一行后因为没有读到换行符而认为读取数据未结束,而一直处于等待中
bufOut.newLine();
bufOut.flush();//读取的数据都存放于缓冲区,必须刷新后才能将数据发送出去
System.out.println(bufIn.readLine());//接收返回数据,并将数据打印在控制台上。
}
buf.close();//关闭键盘输入
s.close();//关闭客服端
}
}