起因
其实我不想写起因,一位面试人家让我写一个套接字,不会,输入输出,不会写。唉。。。 写代码吧,现在想想,我认真写java代码也没多久,慢慢来呗;
套接字
这个怎么理解呢,就是说tcp/udp在运输层,那么上层好多应用都要使用TCP,那么怎么区分呢?这时候就出现了套接字和端口,应用程序自己创建套接字,标记自己的端口,那么分包的时候就有了约束,传回的数据包,也可以根据端口找到位置;代码传送门
Demo时间
下面会有很多Demo 主要参考了 参考一,参考二,主要参考;
Demo1
客户端获取服务器发过来的信息,然后就完了;
public class TestClient {
public static void main(String args[]) {
try {
// 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
// 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
// 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
// refused: connect
Socket s1 = new Socket("127.0.0.1", 8888);
// 打开输入流
InputStream is = s1.getInputStream();
// 封装输入流
DataInputStream dis = new DataInputStream(is);
// 打印服务器端发送过来的信息
System.out.println(dis.readUTF());
System.out.println(dis.readUTF());
// 关闭输入流
dis.close();
// 关闭打开的socket对象
s1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class TestServer {
public static void main(String args[]) {
try {
// 指定服务器端的端口号为8888
ServerSocket s = new ServerSocket(8888);
while (true) {
// 建立连接
Socket socket = s.accept();
// 打开输出流
OutputStream os = socket.getOutputStream();
// 封装输出流
DataOutputStream dos = new DataOutputStream(os);
// s<li>.getInetAddress()获取远程ip地址,s<li>.getPort()远程客户端的端口号
// 向客户端发送数据
dos.writeUTF("你好,客户端地址信息: " + socket.getInetAddress()
+ "\t客户端通信端口号: " + socket.getPort());
dos.writeUTF("i'm a server ,my name is colin!");
// 关闭打开的输出流
dos.close();
// 关闭打开的socket对象
socket.close();
}// 开始下一此循环
} catch (IOException e) {
e.printStackTrace();
}
}
}
题外话:
我们很容易服务器和客户端的形式基本类似这样:
ServerSocket s = new ServerSocket(8888);
while (true) {
Socket socket = s.accept();
/*stream的部分
*/
/*关闭流,关闭连接之类的
*/
}
socket如果接收不到,服务器就会就等着;
将其放在while(true)中,就一直监听;上一个关掉,监听下一个;
Socket socket = s.accept();
对于流来说,这里就很麻烦,一会儿就被绕晕了;输入,输出到底是针对谁来说的呢?
首先我们要清楚读和写;很简单吧,正因为简单,所以我就被弄糊涂了;
考虑我们在纸上写字;我们就将其简化为写;
然后我们抄写一遍,我们就需要先读出来,然后在写下;
这里我们会很容易想到我们写,我们读的;主题对象是我们;
但是考虑我们现在在敲代码;写是肯定的。但是真的在写吗?这是一个问题啊;我们通过键盘输入一段字符,字节流,给了机器,很明显的输入流对比,但是对系统来说,他是读的啊,他得知道你敲了啥啊;
所以输入流是这样一种对象: 读入你的输入,并且已相应的的格式,编码读给系统; 举个例子,大家来学校报道,报道通道相当于一个输入流,不断地来人,报道哪里会有人看你的档案,哦,你叫张三,然后学校知道你叫做张三;这就是输入流做的事情;
翻过来输出流,相当于什么呢?大家毕业了,排着队去照毕业照;不断地人流,到了照相馆照相;咔咔咔,大家就被输出了;这样不生动,我们换成劳动力市场,学校作为主体,输入流就是毕业时一个一个下发的档案,然后大家就可以去找工作了;学校就不管你了,你被输出了;
DEMO2
客户端一直说,服务器一直听;
public class Client {
Socket client;
public Client() {
try {
client = new Socket("localhost", 7777);
OutputStream outputStream = client.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String a;
while (true) {
a = bufferedReader.readLine();
if (a.equals("bye"))
break;
dataOutputStream.writeUTF(a);
}
dataOutputStream.close();
bufferedReader.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Client();
}
public class Server {
private Socket socket;
private ServerSocket ss;
public Server() throws IOException {
ss = new ServerSocket(7777);
socket = ss.accept();
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
while (true) {
String a = dataInputStream.readUTF();
if (a.equals("bye"))
break;
System.out.println(a);
br.readLine());
}
}
public static void main(String[] args) {
try {
new Server();
} catch (IOException e) {
e.printStackTrace();
}
}
}
在这里我们发现一个socket一边写,一边读,像不像是只是一个文件呢?
Demo3
客户端和服务器必须一人一句
public class TestClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",8888);
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String info;
String info1;
while (true)
{
info = bufferedReader.readLine();
dataOutputStream.writeUTF(info);
if (info == "bye")
break;
info1 = dataInputStream.readUTF();
System.out.println("服务器"+info1);
if (info1 == "bye")
break;
}
bufferedReader.close();
dataInputStream.close();
dataOutputStream.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class TestServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = serverSocket.accept();
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String info;
String info1;
while (true)
{
info = dataInputStream.readUTF();
System.out.println("客户端说:"+ info);
if (info.equals("bye"))
break;
info1 = bufferedReader.readLine();
dataOutputStream.writeUTF(info1);
if (info1.equals("bye"))
break;
}
dataInputStream.close();
dataOutputStream.close();
bufferedReader.close();
socket.close();
serverSocket.close();
} catch (SocketException e)
{
System.out.println("网络异常");
}
catch (IOException e) {
e.printStackTrace();
}
}
}
其实这里我们就发现,这其实就是典型的一个TCP的连接了,一个一直监听,一个需要找到正确的ip和端口,才能正确获得socket;
Demo4
其实就是两个线程,一个读,一个写;像不像一个棉花,可以随时咬一口,或者随时放一块;
public class TestClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",8888);
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
new MyClientReader(dataInputStream).start();
new MyClientWriter(dataOutputStream).start();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyClientReader extends Thread{
private DataInputStream dataInputStream;
public MyClientReader(DataInputStream dataInputStream) {
this.dataInputStream = dataInputStream;
}
@Override
public void run() {
String info;
try {
while (true)
{
info = dataInputStream.readUTF();
System.out.println("服务器说:"+info);
if (info.equals("bye")){
System.out.println("对方不想理你了");
System.exit(0);
}
}
} catch (IOException e) {
System.out.println("服务器死翘翘了");
e.printStackTrace();
}
}
}
class MyClientWriter extends Thread {
private DataOutputStream dataOutputStream;
public MyClientWriter(DataOutputStream dataOutputStream) {
this.dataOutputStream = dataOutputStream;
}
@Override
public void run() {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String info;
try {
while (true)
{
info = bufferedReader.readLine();
dataOutputStream.writeUTF(info);
if (info.equals("bye"))
{
System.out.println("感谢使用");
System.exit(0);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class TestServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = serverSocket.accept();
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
new MyClientReader(dataInputStream).start();
new MyServerWriter(dataOutputStream).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyServerReader extends Thread{
private DataInputStream dataInputStream;
public MyServerReader(DataInputStream dataInputStream) {
this.dataInputStream = dataInputStream;
}
@Override
public void run() {
String info;
try {
while (true)
{
info = dataInputStream.readUTF();
System.out.println("客户端说"+info);
if (info.equals("bye")){
System.out.println("对方不想理你了");
System.exit(0);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyServerWriter extends Thread {
private DataOutputStream dataOutputStream;
public MyServerWriter(DataOutputStream dataOutputStream) {
this.dataOutputStream = dataOutputStream;
}
@Override
public void run() {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String info;
try {
while (true)
{
info = bufferedReader.readLine();
dataOutputStream.writeUTF(info);
if (info.equals("bye"))
{
System.out.println("感谢使用");
System.exit(0);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结
- 其实一位套接字是很难的东西,学下来,感觉还是很容易理解的;
- 加油努力吧!