好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

java Socket实现多人群聊与私聊功能

本文实例为大家分享了 java socket实现多人 群聊 与 私聊 的具体代码,供大家参考,具体内容如下

关于socket套接字的一些基本知识与认识可以参见 上一篇 或自行查阅。

serversocket和socket实现群聊与私聊涉及到多线程编程,实现过程的重点是利用socket通信的原理,即不断的在服务端和客户端创建输入输出流来相互传递、交换数据等以达到通信的目的。具体实现如下:

服务端:

?

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

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

import java.io.*;

import java.net.*;

import java.util.hashmap;

import java.util.map;

import java.util.concurrent.executorservice;

import java.util.concurrent.executors;

import java.util.concurrent.threadpoolexecutor;

 

 

public class tcpserver {

 

  private serversocket serversocket;

 

  /**

  * 创建线程池来管理客户端的连接线程

  * 避免系统资源过度浪费

  */

  private executorservice exec;

 

  // 存放客户端之间私聊的信息

  private map<string,printwriter> storeinfo;

 

  public tcpserver() {

  try {

 

  serversocket = new serversocket( 6789 );

  storeinfo = new hashmap<string, printwriter>();

  exec = executors.newcachedthreadpool();

 

  } catch (exception e) {

  e.printstacktrace();

  }

  }

 

  // 将客户端的信息以map形式存入集合中

  private void putin(string key,printwriter value) {

  synchronized ( this ) {

  storeinfo.put(key, value);

  }

  }

 

  // 将给定的输出流从共享集合中删除

  private synchronized void remove(string key) {

  storeinfo.remove(key);

  system.out.println( "当前在线人数为:" + storeinfo.size());

  }

 

  // 将给定的消息转发给所有客户端

  private synchronized void sendtoall(string message) {

  for (printwriter out: storeinfo.values()) {

  out.println(message);

  }

  }

 

  // 将给定的消息转发给私聊的客户端

  private synchronized void sendtosomeone(string name,string message) {

  printwriter pw = storeinfo.get(name); //将对应客户端的聊天信息取出作为私聊内容发送出去

  if (pw != null ) pw.println(message);

  }

 

  public void start() {

  try {

  while ( true ) {

  system.out.println( "等待客户端连接... ... " );

  socket socket = serversocket.accept();

 

  // 获取客户端的ip地址

  inetaddress address = socket.getinetaddress();

  system.out.println( "客户端:[" + address.gethostaddress() + "]连接成功! " );

  /**

  * 启动一个线程,由线程来处理客户端的请求,这样可以再次监听

  * 下一个客户端的连接

  */

  exec.execute( new listenrclient(socket)); //通过线程池来分配线程

  }

  } catch (exception e) {

  e.printstacktrace();

  }

  }

 

  /**

  * 该线程体用来处理给定的某一个客户端的消息,循环接收客户端发送

  * 的每一个字符串,并输出到控制台

  */

  class listenrclient implements runnable {

 

  private socket socket;

  private string name;

 

  public listenrclient(socket socket) {

  this .socket = socket;

  }

 

  // 创建内部类来获取昵称

  private string getname() throws exception {

  try {

  //服务端的输入流读取客户端发送来的昵称输出流

  bufferedreader breader = new bufferedreader(

  new inputstreamreader(socket.getinputstream(), "utf-8" ));

  //服务端将昵称验证结果通过自身的输出流发送给客户端

  printwriter ipw = new printwriter(

  new outputstreamwriter(socket.getoutputstream(), "utf-8" ), true );

 

  //读取客户端发来的昵称

  while ( true ) {

  string namestring = breader.readline();

  if ((namestring.trim().length() == 0 ) || storeinfo.containskey(namestring)) {

  ipw.println( "fail" );

  } else {

  ipw.println( "ok" );

  return namestring;

  }

  }

  } catch (exception e) {

  throw e;

  }

  }

 

  @override

  public void run() {

  try {

  /*

  * 通过客户端的socket获取客户端的输出流

  * 用来将消息发送给客户端

  */

  printwriter pw = new printwriter(

  new outputstreamwriter(socket.getoutputstream(), "utf-8"), true);

 

  /*

  * 将客户昵称和其所说的内容存入共享集合hashmap中

  */

  name = getname();

  putin(name, pw);

  thread.sleep(100);

 

  // 服务端通知所有客户端,某用户上线

  sendtoall("[系统通知] [" + name + "]已上线");

 

  /*

  * 通过客户端的socket获取输入流

  * 读取客户端发送来的信息

  */

  bufferedreader breader = new bufferedreader(

  new inputstreamreader(socket.getinputstream(), "utf-8" ));

  string msgstring = null ;

 

 

  while ((msgstring = breader.readline()) != null ) {

  // 检验是否为私聊(格式:@昵称:内容)

  if (msgstring.startswith( "@" )) {

  int index = msgstring.indexof( ":" );

  if (index >= 0 ) {

  //获取昵称

  string thename = msgstring.substring( 1 , index);

  string info = msgstring.substring(index+ 1 , msgstring.length());

  info = name + ":" + info;

  //将私聊信息发送出去

  sendtosomeone(thename, info);

  continue ;

  }

  }

  // 遍历所有输出流,将该客户端发送的信息转发给所有客户端

  system.out.println(name+ ":" + msgstring);

  sendtoall(name+ ":" + msgstring);

  }

  } catch (exception e) {

  // e.printstacktrace();

  } finally {

  remove(name);

  // 通知所有客户端,某某客户已经下线

  sendtoall( "[系统通知] " +name + "已经下线了。" );

 

  if (socket!= null ) {

  try {

  socket.close();

  } catch (ioexception e) {

  e.printstacktrace();

  }

  }

  }

  }

  }

 

  public static void main(string[] args) {

  tcpserver server = new tcpserver();

  server.start();

  }

}

客户端:

?

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

94

95

96

97

98

99

import java.io.*;

import java.net.*;

import java.util.scanner;

import java.util.concurrent.executorservice;

import java.util.concurrent.executors;

import java.util.concurrent.threadpoolexecutor;

 

public class tcpclient {

 

  static private socket clientsocket;

 

  public tcpclient() {}

 

  public static void main(string[] args) throws exception {

  scanner scanner = new scanner(system.in);

  string serverip;

 

  system.out.println( "请设置服务器ip:" );

  serverip = scanner.next();

  clientsocket = new socket(serverip, 6789 );

  tcpclient client = new tcpclient();

  client.start();

  }

 

  public void start() {

  try {

  scanner scanner = new scanner(system.in);

  setname(scanner);

 

  // 接收服务器端发送过来的信息的线程启动

  executorservice exec = executors.newcachedthreadpool();

   exec.execute( new listenrservser());

 

  // 建立输出流,给服务端发信息

  printwriter pw = new printwriter(

  new outputstreamwriter(clientsocket.getoutputstream(), "utf-8" ), true );

 

  while ( true ) {

  pw.println(scanner.nextline());

  }

  } catch (exception e) {

  e.printstacktrace();

  } finally {

  if (clientsocket != null ) {

  try {

  clientsocket.close();

  } catch (ioexception e) {

  e.printstacktrace();

  }

  }

  }

  }

 

  private void setname(scanner scan) throws exception {

  string name;

  //创建输出流

  printwriter pw = new printwriter(

  new outputstreamwriter(clientsocket.getoutputstream(), "utf-8" ), true );

  //创建输入流

  bufferedreader br = new bufferedreader(

  new inputstreamreader(clientsocket.getinputstream(), "utf-8" ));

 

  while ( true ) {

  system.out.println( "请创建您的昵称:" );

  name = scan.nextline();

  if (name.trim().equals( "" )) {

  system.out.println( "昵称不得为空" );

  } else {

  pw.println(name);

  string pass = br.readline();

  if (pass != null && (!pass.equals( "ok" ))) {

  system.out.println( "昵称已经被占用,请重新输入:" );

  } else {

  system.out.println( "昵称[" +name+ "]已设置成功,可以开始聊天了" );

  break ;

  }

  }

  }

  }

 

  // 循环读取服务端发送过来的信息并输出到客户端的控制台

  class listenrservser implements runnable {

 

  @override

  public void run() {

  try {

  bufferedreader br = new bufferedreader(

  new inputstreamreader(clientsocket.getinputstream(), "utf-8" ));

  string msgstring;

  while ((msgstring = br.readline())!= null ) {

  system.out.println(msgstring);

  }

  } catch (exception e) {

  e.printstacktrace();

  }

  }

  }

 

}

运行结果:

开始自己的实现也不是很完整,后来也是借鉴别人比较好的思想后完善的,权当分享。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

原文链接:https://blog.csdn.net/zhaokx3/article/details/52513019

查看更多关于java Socket实现多人群聊与私聊功能的详细内容...

  阅读:44次