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

java进阶 ------ 基于Socket低层次网络编程

2015-04-20 11:45 621 查看
[本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020]

Socket通讯:

  网络上的两个程序通过一个双向的通讯连接实现数据的交互,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。

  在传统的UNIX环境下可以操作TCP/IP协议的接口不止Socket一个,Socket所支持的协议种类不光是TCP/IP一种,因此两者之间没有必然的联系。在java环境下,Socket编主要是基于TCP/IP协议的网络编程。

Socket通讯的一般过程:

  使用Socket进行Client/Server程序设计的一般连接过程是这样的:Server端Listen(监听)某个端口是否有连接请求,Client端向Server端发回Connect(连接请求), Server端向Client端发回Accept(接受)消息。一个连接就建立起来了。Server端和Client端都可以通过Send,Write等方法与对方通信。

  对于一个功能齐全的Socket,都要包含以下基本结构,其工作过程包含以下四个基本的步骤:

  (1). 创建Socket;

  (2). 打开连接到Socket的输入/出流。

  (3). 按照一定的协议对Socket进行读/写操作。

  (4). 关闭Socket。

创建Socket:

  java在java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。这是两个封装得非常好的类,使用很方便,构造方法如下:

[java] view
plaincopy

Socket();

Socket(Proxy proxy);

Socket(InetAddress address,int port);

Socket(InetAddress address,int port,boolean stream);

Socket(String host,int port);

Socket(String host,int port,boolean stream);

Socket(SocketInmpl impl);

Socket(String host,int port,InetAddress localAddr,int localPort);

Socket(InetAddress address,int port,InetAddress localAddr,int localPort);

ServerSocket();

ServerSocket(int port);

ServerSocket(int port,int backup);

ServerSocket(int port,int backup,InetAddress bindAddr);

  其中,address,host和port分别是双向连接中另一方的ip地址,主机名和端口号,stream指明socket是流socket还是数据报socket,localPort表示本地主机的端口号,localAddr和bindAddr是本地机器的的地址,impl是socket的父类,既可以用来创建serverSocket又可以用来创建Socket。如:

Socket client = new Socket("127.0.0.1",2000);

ServerSocket server = new ServerSocket(2000);

  注意,在选择端口时,需要小心,每个端口提供的一种特定的服务,只有给出正确的端口,才能获得相应的服务,0~1023为系统保留,如http服务端口号80,telent服务端口号21,所以我们在选择端口时,最好选择一个大于1023的数,以防止冲突。

用Socket实现客户端与服务端交互:


  单线程实现:

   如果,客户端与服务端均采用单线程实现通信,则每次双方只能发送一条信息,即按:client发-server收-server发-client收.......这种模式进行通讯,可以观察下列单线程实现代码输出结果:

客户端代码SocketTalkClient.java:

[java] view
plaincopy





package com.jesson.mianshi.network;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

public class SocketTalkClient {

/**

* @param args

*/

public static void main(String[] args) {

SocketTalkClient client = new SocketTalkClient();

// 测试单线程实现的客户端与服务端交互

System.out.println("client: 单线程........");

client.singleThreadTalkClient();

}

/**

* 单线程实现的客户端与服务端通信

*/

public void singleThreadTalkClient() {

try {

Socket socket = new Socket("127.0.0.1", 4700);

// 向本机的4700端口发出客户请求

BufferedReader sin = new BufferedReader(new InputStreamReader(

System.in));

// 由系统标准输入设备构造BufferedReader对象

PrintWriter os = new PrintWriter(socket.getOutputStream());

// 由Socket对象得到输出流,并构造PrintWriter对象

BufferedReader is = new BufferedReader(new InputStreamReader(

socket.getInputStream()));

// 由Socket对象得到输入流,并构造相应的BufferedReader对象

String readline;

readline = sin.readLine(); // 从系统标准输入读入一字符串

while (!readline.equals("bye")) {

os.println(readline);

// 将从系统标准输入读入的字符串输出到Server

os.flush();

// 刷新输出流,使Server马上收到该字符串

System.out.println("Client: " + readline);

try {

System.out.println("Server: " + is.readLine());

} catch (IOException e) {

readline = sin.readLine();

continue;

}

readline = sin.readLine(); // 从系统标准输入读入一字符串

} // 继续循环

os.close(); // 关闭Socket输出流

is.close(); // 关闭Socket输入流

socket.close(); // 关闭Socket

} catch (Exception e) {

System.out.println("error");

}

}

}

服务端代码SocketTalkServer.java:

[java] view
plaincopy





package com.jesson.mianshi.network;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

public class SocketTalkServer {

public static void main(String[] args) {

SocketTalkServer server = new SocketTalkServer();

// 测试单线程实现的客户端与服务端交互

System.out.println("server: 单线程........");

server.singleThreadTalkServer();

}

/**

* 单线程实现的客户端与服务端通信

*/

public void singleThreadTalkServer() {

ServerSocket server = null;

try {

server = new ServerSocket(4700);

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("can not listen to:" + e);

}

Socket socket = null;

try {

socket = server.accept();

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("can not accept socket from client:" + e);

}

String line;

try {

BufferedReader is = new BufferedReader(new InputStreamReader(

socket.getInputStream()));

PrintStream os = new PrintStream(socket.getOutputStream());

BufferedReader sin = new BufferedReader(new InputStreamReader(

System.in));

System.out.println("client: " + is.readLine());

line = sin.readLine();

while (!line.equals("bye")) {

os.println(line);

os.flush();

System.out.println("Server: " + line);

System.out.println("Client: " + is.readLine());

line = sin.readLine();

}

os.close();

is.close();

socket.close();

server.close();

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("error: " + e);

}

}

}

  程序执行输出结果:

客户端输出:

[plain] view
plaincopy





client: 单线程........

hello server

Client: hello server

Server: hello cient

我每次只能发送一条消息

Client: 我每次只能发送一条消息

Server: 我也是

服务端输出:

[plain] view
plaincopy





<span style="font-size:14px;">server: 单线程........

client: hello server

hello cient

Server: hello cient

Client: 我每次只能发送一条消息

我也是

Server: 我也是</span>


  多线程实现:

  可以看出,用单线程实现,客户端每次只能发送一条消息,要实现双方都可以发送任意条消息,这就需要用到多个线程了,这里用了两个线程来实现监听和写。代码如下:

客户端代码(SocketTalkClient.java):

[java] view
plaincopy





package com.jesson.mianshi.network;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

public class SocketTalkServer {

public static void main(String[] args) {

SocketTalkServer server = new SocketTalkServer();

// 测试多线程实现的客户端与服务端交互

System.out.println("server: 多线程........");

server.MultiThreadTalkServer();

}

/**

* 多线程实现的客户端与服务端交互

*/

private void MultiThreadTalkServer() {

ServerSocket server = null;

try {

server = new ServerSocket(4701);

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("can not listen to:" + e);

}

Socket socket = null;

try {

socket = server.accept();

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("can not accept socket from client:" + e);

}

String line;

try {

BufferedReader is = new BufferedReader(new InputStreamReader(

socket.getInputStream()));

PrintWriter os = new PrintWriter(socket.getOutputStream());

BufferedReader sin = new BufferedReader(new InputStreamReader(

System.in));

new ServerLinstenThread(is).start();

new ServerWriteThread(sin, os).start();

/*

* os.close(); is.close(); socket.close(); server.close();

*/

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("error: " + e);

}

}

/**

* 服务端听线程

*

* @author jesson

*

*/

class ServerLinstenThread extends Thread {

private BufferedReader linsten;

public ServerLinstenThread(BufferedReader linsten) {

// TODO Auto-generated constructor stub

this.linsten = linsten;

}

public void run() {

// TODO Auto-generated method stub

String clientInfo;

try {

while (true) {

clientInfo = linsten.readLine();

System.out.println("Client: " + clientInfo);

if (clientInfo.equals("bye")) {

System.out.println("Client下线,程序退出");

System.exit(0);

}

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

/**

* 服务端端写线程

*

* @author jesson

*

*/

class ServerWriteThread extends Thread {

private BufferedReader writer;

private PrintWriter printWriter;

public ServerWriteThread(BufferedReader writer, PrintWriter printWriter) {

this.writer = writer;

this.printWriter = printWriter;

}

public void run() {

// TODO Auto-generated method stub

String serverInfo;

try {

while (true) {

serverInfo = writer.readLine();

printWriter.println(serverInfo);

printWriter.flush();

System.out.println("Server: " + serverInfo);

if (serverInfo.equals("bye")) {

System.out.println("Server自己下线,程序退出");

System.exit(0);

}

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

服务端代码(SocketTalkServer.java):

[java] view
plaincopy





package com.jesson.mianshi.network;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

public class SocketTalkServer {

public static void main(String[] args) {

SocketTalkServer server = new SocketTalkServer();

// 测试多线程实现的客户端与服务端交互

System.out.println("server: 多线程........");

server.MultiThreadTalkServer();

}

/**

* 多线程实现的客户端与服务端交互

*/

private void MultiThreadTalkServer() {

ServerSocket server = null;

try {

server = new ServerSocket(4701);

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("can not listen to:" + e);

}

Socket socket = null;

try {

socket = server.accept();

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("can not accept socket from client:" + e);

}

String line;

try {

BufferedReader is = new BufferedReader(new InputStreamReader(

socket.getInputStream()));

PrintWriter os = new PrintWriter(socket.getOutputStream());

BufferedReader sin = new BufferedReader(new InputStreamReader(

System.in));

new ServerLinstenThread(is).start();

new ServerWriteThread(sin, os).start();

/*

* os.close(); is.close(); socket.close(); server.close();

*/

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("error: " + e);

}

}

/**

* 服务端听线程

*

* @author jesson

*

*/

class ServerLinstenThread extends Thread {

private BufferedReader linsten;

public ServerLinstenThread(BufferedReader linsten) {

// TODO Auto-generated constructor stub

this.linsten = linsten;

}

public void run() {

// TODO Auto-generated method stub

String clientInfo;

try {

while (true) {

clientInfo = linsten.readLine();

System.out.println("Client: " + clientInfo);

if (clientInfo.equals("bye")) {

System.out.println("Client下线,程序退出");

System.exit(0);

}

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

/**

* 服务端端写线程

*

* @author jesson

*

*/

class ServerWriteThread extends Thread {

private BufferedReader writer;

private PrintWriter printWriter;

public ServerWriteThread(BufferedReader writer, PrintWriter printWriter) {

this.writer = writer;

this.printWriter = printWriter;

}

public void run() {

// TODO Auto-generated method stub

String serverInfo;

try {

while (true) {

serverInfo = writer.readLine();

printWriter.println(serverInfo);

printWriter.flush();

System.out.println("Server: " + serverInfo);

if (serverInfo.equals("bye")) {

System.out.println("Server自己下线,程序退出");

System.exit(0);

}

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

  执行上述代码,运行结果:

客户端输出:

[plain] view
plaincopy





client: 多线程........

你好,server

Client: 你好,server

Server: 你好,client

Server: server发送多条信息:

Server: 1. abcd

Server: 2. 1234

Server: 3. ABC

client发送多条消息:

Client: client发送多条消息:

1. xxxxx

Client: 1. xxxxx

2.yyyy

Client: 2.yyyy

3.zzzz

Client: 3.zzzz

bye

Client: bye

Client自己下线,程序退出

服务端输出:

[java] view
plaincopy





server: 多线程........

Client: 你好,server

你好,client

Server: 你好,client

server发送多条信息:

Server: server发送多条信息:

1. abcd

Server: 1. abcd

2. 1234

Server: 2. 1234

3. ABC

Server: 3. ABC

Client: client发送多条消息:

Client: 1. xxxxx

Client: 2.yyyy

Client: 3.zzzz

Client: bye

Client下线,程序退出
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: