说说TCP/IP?
应用层 http ftp ssh dns smtp pop telnet ….
传输层 tcp udp
网络层 ip icmp
链路层 arp rarp
C 在 unix 实现协议相关的代码
计算机世界网络编程统称 socket编程
常用网络相关命令:
ping route nslookup arp netstat ipconfig/ifconfig/ip
import java.net.ServerSocket;
class TcpServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(5555);
System.in.read();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
}
}
}
运行程序后,打开命令行window:netstat -ano| find “:5555”
linux: netstat -anp| grep “:5555”
TcpServer.java
import java.net.ServerSocket;
class TcpServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(5555);
server.accept();
System.in.read();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
}
}
}
YkClient.java
import java.net.ServerSocket;
import java.net.Socket;
class YkClient {
public static void main(String[] args) {
try {
new Socket("localhost", 5555);
System.in.read();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
先运行服务器,再运行客户端,使用netstat查看信息
YkClient.java
import java.net.ServerSocket;
import java.net.Socket;
class YkClient {
public static void main(String[] args) {
try {
Socket socket= new Socket("localhost", 5555);
socket.getOutputStream().write("i'myangkang".getBytes());
System.in.read();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
TcpServer.java
import java.net.ServerSocket;
import java.net.Socket;
class TcpServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(5555);
Socket socket=server.accept();
byte b[]=new byte[100];
int len= socket.getInputStream().read(b);
System.out.println(new String(b, 0, len));
System.in.read();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
}
}
}
运行服务器,如果出现bind问题,说明占用端口的进程还在运行,杀掉占用端口的进程再运行即可
YkClient.java
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
class YkClient {
public static void main(String[] args) {
try {
Socket socket= new Socket("localhost", 5555);
OutputStream out= socket.getOutputStream();
String str = null;
byte bMsg[] = new byte[200];
while (true) {
System.out.print("ykclient>");
int len = System.in.read(bMsg);
if (len == 2)
continue;
str = new String(bMsg, 0, len - 2);
if (str.equals("quit") || str.equals("exit")) {
System.exit(0);
}
out.write(bMsg, 0, len-2);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
TcpServer.java
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
class TcpServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(5555);
Socket socket = server.accept();
InputStream in = socket.getInputStream();
byte b[] = new byte[100];
while (true) {
int len = in.read(b);
System.out.println(new String(b, 0, len));
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
}
}
}
运行效果
2018年12月3日星期一
软件、程序、进程、线程
打开任务管理器,查看mysql服务器进程的线程数量
每个人用mysql客户端和我们自己的写的客户端连接mysql数据库
再看看线程的数量
不停使用mysql客户端连接服务器,直到看到线程数量增加
线程可以看着是程序里面的小程序,是可以独立运行的代码段,线程这个功能是CPU和OS提供的,不是语言提供的
并发 和 并行概念?
class ThreadA extends Thread {
@Override
public void run() {
// for 输出1 3 5 7 9
for (int i = 1; i <= 9; i = i + 2) {
System.out.println(i);
try {
sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class ThreadB implements Runnable {
@Override
public void run() {
// do while输出2 4 6 8 10
int i = 2;
do {
System.out.println(i);
i = i + 2;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} while (i <= 10);
}
}
class TestT {
public static void main(String[] args) {
Thread t1 = new ThreadA();
Thread t2 = new Thread(new ThreadB());
t1.start();
t2.start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 4; i++) {
System.out.println(i);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
}
将程序多运行几次,看输出结果
调整网络程序、增加线程
调整服务器代码
TcpServer.java
import java.net.ServerSocket;
import java.net.Socket;
class TcpServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(5555);
while (true) {
Socket socket = server.accept();
new CommThread(socket).start();
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
}
}
}
创建线程处理和每个客户端的通信
import java.io.InputStream;
import java.net.Socket;
class CommThread extends Thread {
private Socket socket;
public CommThread() {
}
public CommThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
// 写和每一个客户端通信的代码,怎么区分不同客户端(通过Socket)
try {
System.out.println(getName() + "-" + socket);
InputStream in = socket.getInputStream();
byte b[] = new byte[200];
while (true) {
int len = in.read(b);
System.out.println(new String(b, 0, len));
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
客户端代码不变
YkClient.java
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
class YkClient {
public static void main(String[] args) {
try {
Socket socket= new Socket("localhost", 5555);
OutputStream out= socket.getOutputStream();
String str = null;
byte bMsg[] = new byte[200];
while (true) {
System.out.print("ykclient>");
int len = System.in.read(bMsg);
if (len == 2)
continue;
str = new String(bMsg, 0, len - 2);
if (str.equals("quit") || str.equals("exit")) {
System.exit(0);
}
out.write(bMsg, 0, len-2);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
布置一个任务,创建一张表
msginfo(id 自动增长字段, msg varchar(200), msgdate date);
自动增长字段:Oracle 使用sequence ;mysql使用auto_increment。
使用jdbc将聊天消息保存到数据库
public void run() {
// 写和每一个客户端通信的代码,怎么区分不同客户端(通过Socket)
try {
System.out.println(getName() + "-" + socket);
InputStream in = socket.getInputStream();
byte b[] = new byte[200];
while (true) {
int len = in.read(b);
String msg=new String(b, 0, len);
// 使用jdbc将消息保存到数据库
String sql="insert into msginfo(msg,msgdate) values('"+msg+"',sysdate/now())";
System.out.println(sql);//输出sql检查sql是否正确
System.out.println(msg);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
提醒:先运行程序,客户端发个消息,服务器端能看到正确的sql语句后再将jdbc操作代码搬过来
写一个执行insert/delete/update的
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
class Db {
private Connection getConn() {
Connection conn = null;
try {
// 把和数据库建立连接的代码复制过来
Class.forName("driver");
conn = DriverManager.getConnection("url", "user", "pass");
} catch (Exception e) {
System.err.println(e.getMessage());
}
return conn;
}
public boolean exeUpdate(String sql) throws SQLException {
Connection conn = getConn();
try {
Statement st = conn.createStatement();
int cnt = st.executeUpdate(sql);
return cnt > 0;
} catch (Exception e) {
System.err.println(e.getMessage());
return false;
} finally {
if (conn != null) {
conn.close();
}
}
}
}
public void run() {
// 写和每一个客户端通信的代码,怎么区分不同客户端(通过Socket)
try {
System.out.println(getName() + "-" + socket);
InputStream in = socket.getInputStream();
byte b[] = new byte[200];
while (true) {
int len = in.read(b);
String msg=new String(b, 0, len);
// 使用jdbc将消息保存到数据库
String sql="insert into msginfo(msg,msgdate) values('"+msg+"',sysdate/now())";
new Db().exeUpdate(sql);
System.out.println(msg);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
如何将每个客户端发的消息发送到其他客户端?
只要记住有哪些客户端就行了
调整服务器
class TcpServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(5555);
List<Socket> lst=new ArrayList<Socket>();
while (true) {
Socket socket = server.accept();
lst.add(socket);
new CommThread(socket, lst).start();
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
}
}
}
调整线程
class CommThread extends Thread {
private Socket socket;
private List<Socket> lst;
public CommThread() {
}
public CommThread(Socket socket, List<Socket> lst) {
super();
this.socket = socket;
this.lst = lst;
}
private void pushMsg(byte b[], int len) {
for (Socket skt : lst) {
if (skt == socket) {
continue;
}
try {
OutputStream out = skt.getOutputStream();
out.write(b, 0, len);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
@Override
public void run() {
// 写和每一个客户端通信的代码,怎么区分不同客户端(通过Socket)
try {
InputStream in = socket.getInputStream();
byte b[] = new byte[200];
while (true) {
int len = in.read(b);
String msg = new String(b, 0, len);
// 使用jdbc将消息保存到数据库
String sql = "insert into msginfo(msg,msgdate) values('" + msg + "',sysdate/now())";
new Db().exeUpdate(sql);
// 只要将收到的消息向其他客户端发送
pushMsg(b, len);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
调整客户端
class YkClient {
public static void main(String[] args) {
try {
Socket socket= new Socket("localhost", 5555);
// 创建一个线程对象专门接收服务器发来的信息
OutputStream out= socket.getOutputStream();
String str = null;
byte bMsg[] = new byte[200];
while (true) {
System.out.print("ykclient>");
int len = System.in.read(bMsg);
if (len == 2)
continue;
str = new String(bMsg, 0, len - 2);
if (str.equals("quit") || str.equals("exit")) {
System.exit(0);
}
out.write(bMsg, 0, len-2);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}