我使用套接字编程在Java中创建了一个简单的客户端服务器程序,但是我无法理解该程序的基本控制流程。
客户档案
public static void main(String args[]) throws UnknownHostException, IOException, InterruptedException{
1. System.out.println("CLIENT: "+"client main method started");
2. Socket s=new Socket("localhost",23456);
3. BufferedWriter br=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
4. br.write("CLIENT: "+"here comes the client message");
5.br.flush();
}
服务器文件
public static void main(String args[]) throws IOException, InterruptedException{
11. System.out.println("Server is started");
12. ServerSocket ser=new ServerSocket(23456);
13. Socket s=ser.accept();
14. System.out.println("SERVER: "+"Server is now accepting connections");
15. System.out.println("SERVER: "+"client connected");
16. BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
17. String str=br.readLine();
18. System.out.println("SERVER: "+"Client Message: "+str);
}
如果有人可以在LINE NUMBERS的帮助下,即按声明说明,请向我解释程序的流程,这将非常有帮助。
P.S - 服务器文件的行号从11开始,只是为了方便起见。
谢谢。
答案 0 :(得分:4)
我理解它的方式,任何服务器/客户端应用程序的常规流程是:
已建立服务器套接字。
服务器正在侦听传入连接上的端口23456(阻塞等待)。解除阻塞后,解除阻塞的连接请求将存储在Socket中。
客户端通过Socket向服务器发送消息,服务器在解除阻塞时立即存储。
服务器唤醒,因为它收到了一条消息(解除阻塞),并建立了Socket连接。
服务器从客户端读取消息。 (如果跳过此步骤,客户端通常会感到困惑)。这是通过Socket接受完成的。
服务器通过接收的Socket写入流生成对客户端的响应并发送它。
服务器关闭(接受Socket的)输出流以指示通信结束。 (这是必需的)。
相关示例:
这是一个相对简单的(不是真的,但我试图尽可能明确)自包含的Web服务器,它可以侦听端口80.运行后,转到http://127.0.0.1:80查看默认页面。在此程序中,客户端是您的Web浏览器(或尝试在localhost 80上侦听的任何其他程序)
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import javax.swing.*;
import java.awt.*;
import jserv.*;
public class JavaServer
{
public static void main(String[] args)
throws Exception
{
ServerSocket server = null;
Socket conn = null;
BufferedReader in = null;
PrintWriter out = null;
String msg = null;
ArrayList<String> tcp_get = null;
System.out.println("server> Starting!");
server = new ServerSocket(80);
while (true) {
System.out.println("server> Waiting on a connection.");
conn = server.accept();
System.out.println("server> Obtaining io handles.");
out = new PrintWriter(conn.getOutputStream(), true);
in = new BufferedReader (
new InputStreamReader (
conn.getInputStream()
)
);
System.out.println("server> We get signal.");
while ((msg = in.readLine()) != null) {
System.out.println(" " + msg);
/* done if empty line or null. */
if (msg.isEmpty()) {
System.out.println("-- all client info is read --");
break;
}
/* additional protocol handling. */
if (msg.startsWith("GET")) {
tcp_get = get_decode(msg);
}
}
System.out.println("server> sending a message to client.");
/* send the HTML data. acknowledge? */
/* header */
out.write("HTTP/1.0 200 OK\r\n");
out.write("Content-Type: text/html\r\n");
out.write("\r\n");
/* response division. */
System.out.println("tcp_get empty: " + tcp_get.isEmpty());
if (!tcp_get.isEmpty()) {
String page = tcp_get.get(0);
/* we have a page request. */
if (isValidPage(page)) {
File f = new File(page);
try {
Scanner br = new Scanner(new FileInputStream(f));
String s;
while ((s = br.nextLine()) != null) {
out.write(s + "\r\n");
}
br.close();
out.write("\r\n");
System.out.println("server> closing stream.");
} catch (FileNotFoundException e) {
out.write("<p>ERROR 404!</p>\r\n");
out.write("\r\n");
System.out.println("sent default message.");
} catch (Exception e) {}
}
/* once the stream is closed, the client will receive the data."); */
} else {
out.write("<p>Welcome to the default page!</p>\r\n");
out.write("\r\n");
}
out.close();
System.out.println("server> end of communication.");
}
}
private static boolean isValidPage(String page)
{
Pattern pat = Pattern.compile("\\w+\\.html");
Matcher mat = pat.matcher(page);
return mat.matches();
}
private static ArrayList<String> get_decode(String get)
{
ArrayList<String> tmp = new ArrayList<String>();
Pattern pat;
Matcher mat;
String page;
String page_pattern = "\\w+\\.html";
String arg_pattern = "\\w+=\\w+";
String gt = get.replaceFirst(page_pattern, "");
/* obtain the page name. */
pat = Pattern.compile(page_pattern);
mat = pat.matcher(get);
if (!mat.find()) {
System.out.println("decode> GET invalid.");
return tmp;
} else {
page = mat.group();
System.out.println("GET requests " + page);
tmp.add(page);
}
/* strip name from get. */
gt = get.replaceFirst(page_pattern, "");
/* obtain the arguments. */
pat = Pattern.compile(arg_pattern);
mat = pat.matcher(gt);
while (mat.find()) {
System.out.println("argument: " + mat.group());
tmp.add(mat.group());
}
return tmp;
}
}
根据您的实际代码,请回顾一下我列出的7个点的代码。
import java.net.*;
import java.io.*;
class Client {
public static void main(String args[]) throws Exception {
System.out.println("client> started.");
Socket s = new Socket("localhost", 23456);
BufferedWriter br = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
// all messages must end with two linefeeds.
br.write("hello, world!\n\n");
// two linefeeds with no messages indicates end.
br.write("\n\n");
// see part 7. closing the stream flushes the output.
br.close();
}
}
class Server {
public static void main(String args[]) throws Exception {
ServerSocket ser = null;
Socket s = null;
BufferedReader br = null;
String str = null;
System.out.println("server> started");
ser = new ServerSocket(23456);
s = ser.accept();
System.out.println("server> we get signal.");
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
while ((str = br.readLine()) != null) {
if (str.isEmpty()) {
System.out.println("server> everything is received.");
break;
}
System.out.println("server> got message: " + str);
}
System.out.println("server> done.");
}
}
答案 1 :(得分:1)
正如Jose Luis所说,服务器必须具有正确的配置才能连接到客户端,
11 - &gt; 12 - &gt; 13 - &gt; 14然后1 - > 2 - &GT; 3 - &GT; 4 - &GT; 5
此后服务器和客户端可以交换信息
看一下这个描述性图片:
答案 2 :(得分:1)
客户端非常简单。它打开一个到服务器的套接字并写入它。
服务器更复杂。第12行在指定端口上创建套接字。第13行将等待客户端连接到该端口并发送消息。然后第16-18行相当简单。他们从套接字中读取消息(由客户端放在那里)并打印出来。