(1)目的:对网络开发的知识进行一定的实践,增强对网络开发的了解
(2)技术:1、简单的套接字的运用
2、简单的静态方法和变量的使用
3、基本的方法,如构造方法,hasmap的使用
4、多线程
(3)代码
1、这是我们的客户端
package online;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class client1 {
public static void main(String [] args) throws IOException {
//链接我们设置的服务端
Socket socket = new Socket("10.129.0.123", 32917);
//从终端输入我们的信息
BufferedReader getline = new BufferedReader(new InputStreamReader(System.in));
//创建一个字符串来接收我们的输入
BufferedReader serint=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//接收从服务器回来的信息
PrintStream output = new PrintStream(socket.getOutputStream());
String mline;
while(true) {
String line = getline.readLine();
mline=ruler.login + line + ruler.login;
output.println(mline);
String buget=serint.readLine();
System.out.println(buget);
if(buget.length()==4){
System.out.println("登录成功!请记住你的昵称:"+line);break;
}
else {
System.out.println("登入失败,此昵称已被他人使用");
continue;
}
}//默认进去后首先选择的是输入名称
player playtemp=new player(socket);//一个子线程,不断打印从服务器端打印出来的数据
playtemp.start();//使这个线程进入就绪状态
while((mline=getline.readLine())!=null){
//output.println(ruler.person+mline+ruler.person);
output.println(mline);
}
}
}
class client2{
public static void main(String [] args) throws IOException {
//链接我们设置的服务端
Socket socket = new Socket("10.129.0.123", 32917);
//从终端输入我们的信息
BufferedReader getline = new BufferedReader(new InputStreamReader(System.in));
//创建一个字符串来接收我们的输入
BufferedReader serint=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//接收从服务器回来的信息
PrintStream output = new PrintStream(socket.getOutputStream());
String mline;
while(true) {
String line = getline.readLine();
mline=ruler.login + line + ruler.login;
output.println(mline);
String buget=serint.readLine();
System.out.println(buget);
if(buget.length()==4){
System.out.println("登录成功!请记住你的昵称:"+line);break;
}
else {
System.out.println("登入失败,此昵称已被他人使用");
continue;
}
}//默认进去后首先选择的是输入名称
player playtemp=new player(socket);//一个子线程,不断打印从服务器端打印出来的数据
playtemp.start();//使这个线程进入就绪状态
while((mline=getline.readLine())!=null){
output.println(mline);
}
}
}
2、我们的服务端,这里采用了多线程的使用
package online;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class serviver {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(32917);//设置这个类的端口
//这里使用了对象方法的形式
while (true) {//接收多个客户端
Socket persocket = server.accept();//不停的接收客户端的输入
playermannager player = new playermannager(persocket);
player.start();
}
}
}
3、客户端子线程
package online;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class player extends Thread {
Socket socket;
public player(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
BufferedReader mget=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String mline;
while((mline=mget.readLine())!=null){
System.out.println(mline);
}
} catch (IOException e) {
}
}
}
4、服务端子线程
package online;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.HashMap;
public class playermannager extends Thread{
public static HashMap box=new HashMap<>();
//设置一个静态键值对管理我们的客户端口和套接字
Socket socket;
public playermannager(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader mread;
PrintStream moutput;
try{
mread=new BufferedReader(new InputStreamReader(socket.getInputStream()));
moutput=new PrintStream(socket.getOutputStream());
System.out.println("链接成功");
String mgetline;//创建一个字符串接收子类的信息
while((mgetline = mread.readLine())!=null) {
System.out.println(mgetline);
if (mgetline.startsWith(ruler.login) && mgetline.endsWith(ruler.login)) {
String name = mgetline.substring(2, (mgetline.length() - 2));//条件语句,客户是否选择了登录
if (chooselogin(name)) {//引用了这个方法
playermannager.box.put(name, socket);//将这个套接字和名称一起放入我们之前准备的那个变量
System.out.println(playermannager.box.entrySet());
moutput.println("true");//传输给相应的子类
} else {
moutput.println("false");
continue;
}
}
//创建一个私聊代码块
if (mgetline.startsWith(ruler.person) && mgetline.endsWith(ruler.person)) {
//创建一个字符串接受这些信息
int len = mgetline.length() - 2;//一个整型记录其字符串的长度-2
String mgetline2 = mgetline.substring(2, len);//去调我们的前缀和后缀
String[] str = mgetline2.split(ruler.mytry);//按照我们规定的规则分割这个字符串
String mnametemp = str[0];//分割会形成两个数组
System.out.println(str[0]);
String connet = str[1];
Socket hesocket = playermannager.namesocket(mnametemp);//得到我们私聊对象的套接字
String myname=playermannager.socketname(socket);
PrintStream heout = new PrintStream(hesocket.getOutputStream());//输出
heout.println(myname + "对你说:" + connet);
}
if(mgetline.startsWith(ruler.persons) && mgetline.endsWith(ruler.persons)){
//还是创建一个字符串接受这些信息
String nametemp1=playermannager.socketname(socket);
for(String nametemp2:box.keySet()){
Socket sockettemp=box.get(nametemp2);
PrintStream outtemp=new PrintStream(sockettemp.getOutputStream());
outtemp.println(nametemp1+"群发说:"+mgetline);
}
}
}
}catch (IOException e){
}
}
public boolean chooselogin(String name){//一个对象方法,检查是否有重名现象
for(String key:box.keySet()){
if(key.equals(name)){
return false;
}
}
return true;
}
public static Socket namesocket(String name){//创建一个方法同过名字找到套接字
return box.get(name);
}
public static String socketname(Socket socket){//创建一个方法同过套接字找到名字
for(String key:box.keySet()){
if(box.get(key)==socket)return key;
}
return null;
}
}
5、一些常量,我放在一个类里了,果然,这里用线程要代码要好看点
package online;
public class ruler {
public static final String login="a+";
public static final String person="b+";
public static final String persons="c+";
public static final String mytry="&&";
}
感悟:网络开发的学习也有几天了,感觉这个阶段的代码学习就很神奇,有些错误错误总是在你觉得不可能出错时出现,留下我一脸的懵逼和被迫百度短则一两分钟多达一个多小时的无奈,关键是,还不一定搞的定。总的来说,这个阶段进度可以感觉到不是很快,不用很费力就能跟上。可是知识的学习,嗯,,,要多敲代码去检验呀,要多敲代码去检验呀,要多敲代码去检验呀!