Java网络编程之简单的服务端客户端应用实例

本文实例讲述了Java网络编程之简单的服务端客户端应用。分享给大家供大家参考。具体如下:

在Java中,我们使用java.net.Socket及其相关类来完成有关网络的相关功能。Socket类非常简单易用,因为Java技术隐藏了建立网络连接和通过连接发送数据的复杂过程。下面所说的内容只适用于TCP协议。

一、连接到服务器

我们可以使用Socket类的构造函数来打开一个套接字,如

?

1

Socket sk = new Socket("210.0.235.14",13);

其中,210.0.235.14是一个点分十进制的String对象,表示目的主机的IP地址(或主机名), 13表示指定连接目标主机的13端口。这里的210.0.235.14是位于香港的一个授时服务器,授时服务器默认的端口一般都为13.
注意,在成功连接到服务器之前,程序会阻塞。
接下来可以使用Socket类的getInputStream()方法来得到一个InputStream对象,通过这个对象就可以获取到目标主机给我们发过来的信息:

?

1

InputStream inStream = sk.getInputStream();

同理,要向目标主机发送数据,则可以调用getOutputStream()方法来获取一个输出流对象。
下面的例子功能是连接授时服务器,并将返回的信息打印到标准输出中:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

try

{

Socket sk = new Socket("210.0.235.14",13);

sk.setSoTimeout(3000);

InputStream inStream = sk.getInputStream();

//得到输入流对象

Scanner sc = new Scanner(inStream);

//将数据打印到控制台

while(sc.hasNextLine())

{

String str = sc.nextLine();

System.out.println("Output : " + str);

}

sk.close();

}

catch(SocketTimeoutException e) //超时异常

{

System.out.println("Time Out!");

}

catch(Exception e)

{

e.printStackTrace();

}

代码中setSoTimeout()方法可以设置超时时间,即如果超过了设定时间还没有完成读写操作,则会抛出SocketTimeoutException,可以通过捕获这个异常来关闭连接。
另外还有一个超时问题是必须要解决的,就是这个Socket类的构造函数

?

1

new Socket(host,port);

会一直无限地阻塞下去,直到成功建立了到目标主机的连接为止。这当然不是我们所希望的。我们可以通过如下调用方式解决此问题:

?

1

2

3

Socket sk = new Socker();

sk.connect(new InetSocketAddress(host,port),2000);

//设置超时时间为2秒

二、获取主机地址

InetAddress类的静态方法getByName(hostname)可以返回代表了某个主机地址的InetAddress对象,这个对象封闭了一个4字节的序列,即主机的IP地址。然后再调用getHostAddress()方法返回一个表示IP地址的String对象.

一些访问量大的主机名通常会对应着多个IP地址以实现负载均衡。我们可以调用getAllByName()方法来获得所有主机地址,该方法返回一个InetAddress对象的数组。

下面是一个简单的小程序,实现的功能是,如果不在命令行中设置参数,就打印出本地的IP地址,如果指定了主机名,则打印出该主机所有的IP地址:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

package cls;

import java.net.*;

public class ShowIP

{

public static void main(String[] args)

{

try

{

if(args.length > 0)

{

String hostName = args[0]; //主机名

InetAddress[] addr = InetAddress.getAllByName(hostName);

//得到该主机的所有地址

//打印输出至控制台

for(InetAddress address : addr)

{

System.out.println(address.getHostAddress());

}

}

else

{

System.out.println(InetAddress.getLocalHost().getHostAddress());

}

}

catch(Exception e)

{

e.printStackTrace();

}

}

}

三、服务器端程序

服务器端应用程序使用ServerSocket类来创建套接字,并钭其绑定至本地端口中,如

?

1

ServerSocket sock = new ServerSocker(8000);

sock.accept()方法让程序不停地等待连接,该方法只有当有客户端连接时才会返回一个代表了新连接的Socket对象,即该方法会发生阻塞。
这里一般要为每个连接新开启一个线程为其服务。
下面是一个完整的例子,服务端在8400端口处等待连接,每当连接到来时,新开一个线程为其服务,并将连接信息写入的日志文件中:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

package cls;

import java.io.*;

import java.net.*;

import java.util.*;

public class ServerDemo

{

/**

* @param args

*/

public static void main(String[] args)

{

try

{

//ServerSocket servSocket = new ServerSocket(8000);

ServerSocket servSocket = new ServerSocket(8400);

int amount = 0;

while(true)

{

Socket client = servSocket.accept();

++amount;

Date time = new Date();

String prompt = time.toString() + ": 第" + amount + "个用户 " + client.getInetAddress().getHostAddress() + " 已连接\n";

System.out.print(prompt); //在控制台输出信息

ServerDemo.writeLog(prompt); //写入到文件中

//start a new Thread

Thread th = new Thread(new ServThread(client,amount));

th.start();

}

}

catch(Exception e)

{

e.printStackTrace();

}

}

//写入日志文件

public static void writeLog(String str)

{

File logFile = new File("server-log.txt");

try

{

FileWriter out = new FileWriter(logFile,true);

out.append(str);

out.close();

}

catch(Exception e)

{

e.printStackTrace();

}

}

}

/*

* 服务线程类

*/

class ServThread implements Runnable

{

private Socket client;

private int ix;

public ServThread(Socket soc,int ix)

{

client = soc;

this.ix = ix;

}

public void run()

{

try

{

InputStream inStream = client.getInputStream();

OutputStream outStream = client.getOutputStream();

Scanner recv = new Scanner(inStream);

PrintWriter send = new PrintWriter(outStream,true);

send.println("欢迎~随便聊几句吧![输入'bye'关闭联接]");

while(recv.hasNextLine())

{

String str = recv.nextLine();

if(str.equals("bye"))

{

send.println("See you later ~ ^-^");

break;

}

send.println("这是个测试程序,现在还没有什么功能哦");

}

Date time = new Date();

String prompt = time.toString() + ": 第" + ix + "个用户 " + client.getInetAddress().getHostAddress() + " 已断开连接\n";

System.out.print(prompt);

ServerDemo.writeLog(prompt); //写入到文件中

client.close();

}

catch(Exception e)

{

e.printStackTrace();

}

}

}

这个程序已经被放到了服务器上,大家可以使用telnet youthol.tk 8400 命令来体验一下这个程序的运行结果

希望本文所述对大家的java程序设计有所帮助。

本文链接:https://my.lmcjl.com/post/12987.html

展开阅读全文

4 评论

留下您的评论.