一个简单的服务器端与多个客户端进行通信

jiang5495 2009-05-16 10:59:54
一个简单的服务器端与多个客户端进行通信,
每次都是服务器先运行,那么端口就已经确定了,那么就只能与一个客户端进行通信,
我想加入多线程,实现多人通信,但是不知怎么样使用多个端口???
我想根据客户端所使有的端口来确定服务器端使用的端口,但不知怎么实现???

不知一般多线程中,这个端口问题该如何解决????
...全文
561 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
xmoon1983 2010-03-05
  • 打赏
  • 举报
回复
引用 6 楼 jiang5495 的回复:
这是常识性错误。服务器只用一个端口就可以与多个客户端通信。

如何用一个端口去实现呢???
能不能给点思路


服务器对外公开的是域名(IP)和端口,
比如sohu的http服务器:www.sohu.com:80。
但这个80端口只是监听端口,
并不用来实际传输数据。

而浏览器连接到sohu的http服务器时,
服务器会新建一个socket,用来和浏览器通信。
这个socket的端口就不是 80 了。
jiang5495 2009-05-17
  • 打赏
  • 举报
回复
客户端的程序:
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.*;

public class J_ChatClient extends JFrame
{
private ObjectInputStream m_input; // 输入流
private ObjectOutputStream m_output; // 输出流
private JTextField m_enter; // 输入区域
private JTextArea m_display; // 显示区域

public J_ChatClient( ) // 在图形界面中添加组件
{
super("聊天程序客户端");
Container c = getContentPane( );
m_enter = new JTextField( );
m_enter.setEnabled( false );
m_enter.addActionListener(new ActionListener( )
{
public void actionPerformed( ActionEvent event )
{ // 向服务器端发送数据
try
{
String s = event.getActionCommand( );
m_output.writeObject( s );
m_output.flush( );
mb_displayAppend( "客户端: " + s );
m_enter.setText( "" ); // 清除输入区域的原有内容
}
catch (Exception e)
{
System.err.println("发生异常:" + e);
e.printStackTrace( );
} // try-catch结构结束
} // 方法actionPerformed结束
} // 实现接口ActionListener的内部类结束
); // addActionListener方法调用结束
c.add( m_enter, BorderLayout.NORTH );
m_display = new JTextArea( );
c.add( new JScrollPane( m_display ), BorderLayout.CENTER );
} // J_ChatClient构造方法结束

public void mb_displayAppend( String s )
{
m_display.append( s + "\n" );
m_display.setCaretPosition( m_display.getText( ).length( ) );
m_enter.requestFocusInWindow( ); // 转移输入焦点到输入区域
} // 方法mb_displayAppend结束

public boolean mb_isEndSession( String m )
{
if (m.equalsIgnoreCase("q"))
return(true);
if (m.equalsIgnoreCase("quit"))
return(true);
if (m.equalsIgnoreCase("exit"))
return(true);
if (m.equalsIgnoreCase("end"))
return(true);
if (m.equalsIgnoreCase("结束"))
return(true);
return(false);
} // 方法mb_isEndSession结束

public void mb_run( String host, int port)
{
try
{
mb_displayAppend("尝试连接");
Socket s = new Socket(host, port);
String m; // 来自服务器端的消息
m_output = new ObjectOutputStream( s.getOutputStream( ) );
m_input = new ObjectInputStream( s.getInputStream( ) );
m_enter.setEnabled( true );
do
{
m = (String) m_input.readObject( );
mb_displayAppend("服务器端: " + m);
} while(!mb_isEndSession( m ));// do-while循环结束
m_output.writeObject("q"); // 通知服务器端退出程序
m_output.flush( );
m_output.close( );
m_input.close( );
s.close( );
System.exit( 0 );
}
catch (Exception e)
{
System.err.println("发生异常:" + e);
e.printStackTrace( );
mb_displayAppend("发生异常");
} // try-catch结构结束
} // 方法mb_run结束

public static void main(String args[ ])
{
J_ChatClient app = new J_ChatClient( );
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(350, 150);
app.setVisible(true);
if ( args.length == 0 )
app.mb_run("localhost", 5000);
else app.mb_run(args[0], 5000);
} // 方法main结束
} // 类J_ChatClient结束
jiang5495 2009-05-17
  • 打赏
  • 举报
回复
回复楼上,我是这样写的啊,为什么没用啊?????
想了很久没想明白,是为什么???

试着写的一人简单通信程序,为什么服务器只能与一个客户进行通信,而其它客户发的信息,服务器接收不到呢????



服务器端的程序:
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.*;

public class J_ChatServer extends JFrame
{
public static ObjectInputStream m_input; // 输入流
public static ObjectOutputStream m_output; // 输出流
public static JTextField m_enter; // 输入区域
public static JTextArea m_display; // 显示区域
public static int m_clientNumber = 0; // 连接的客户数


//服务器端界面设计
public J_ChatServer( ) // 在图形界面中添加组件
{
super("聊天程序服务器端");
Container c = getContentPane( );
m_enter = new JTextField( );
m_enter.setEnabled( false );
m_enter.addActionListener(new ActionListener( )
{
public void actionPerformed( ActionEvent event )
{ // 向客户端发送数据
try
{
String s = event.getActionCommand( );
m_output.writeObject( s );
m_output.flush( );
mb_displayAppend( "服务器端: " + s );
m_enter.setText( "" ); // 清除输入区域的原有内容
}
catch (Exception e)
{
System.err.println("发生异常:" + e);
e.printStackTrace( );
} // try-catch结构结束
} // 方法actionPerformed结束
} // 实现接口ActionListener的内部类结束
); // addActionListener方法调用结束
c.add( m_enter, BorderLayout.NORTH );
m_display = new JTextArea( );
c.add( new JScrollPane( m_display ), BorderLayout.CENTER );
} // J_ChatServer构造方法结束



//对显示区进行处理,使显示区能显示出最新聊天记录
public static void mb_displayAppend( String s )
{
m_display.append( s + "\n" );
m_display.setCaretPosition( m_display.getText( ).length( ) );
m_enter.requestFocusInWindow( ); // 转移输入焦点到输入区域
} // 方法mb_displayAppend结束




//通知客户端,聊天程序已结束
public static boolean mb_isEndSession( String m )
{
if (m.equalsIgnoreCase("q"))
return(true);
if (m.equalsIgnoreCase("quit"))
return(true);
if (m.equalsIgnoreCase("exit"))
return(true);
if (m.equalsIgnoreCase("end"))
return(true);
if (m.equalsIgnoreCase("结束"))
return(true);
return(false);
} // 方法mb_isEndSession结束





//启动服务器
public void mb_run( )
{
try
{
ServerSocket server = new ServerSocket(5000);
String m; // 来自客户端的消息
while (true)
{
m_clientNumber++;
mb_displayAppend("等待连接[" + m_clientNumber + "]");
Socket s = server.accept( ); //每联结到一个新的客户,就启动一个新的线程
MyThread mythread=new MyThread(s);
mythread.start();

} // while循环结束
}
catch (Exception e)
{
System.err.println("发生异常:" + e);
e.printStackTrace( );
mb_displayAppend("连接[" + m_clientNumber + "]发生异常");
} // try-catch结构结束
} // 方法mb_run结束

public static void main(String args[ ])
{
J_ChatServer app = new J_ChatServer( );

app.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
app.setSize(350, 150);
app.setVisible(true);
app.mb_run( );
} // 方法main结束
} // 类J_ChatServer结束






//构造一个线程类,实现服务器同时与多个客户进行聊天
class MyThread extends Thread
{
Socket s;
String m; // 来自客户端的消息
public MyThread(Socket s)
{
this.s=s;
}

public void run() //实现与客户端的通信
{

try
{

J_ChatServer.mb_displayAppend("接收到客户端连接[" + J_ChatServer.m_clientNumber + "]");
J_ChatServer.m_output = new ObjectOutputStream( s.getOutputStream( ) );
J_ChatServer.m_input = new ObjectInputStream( s.getInputStream( ) );
J_ChatServer.m_output.writeObject("连接成功");
J_ChatServer.m_output.flush( );
J_ChatServer.m_enter.setEnabled( true );
do
{
m = (String) J_ChatServer.m_input.readObject( );
J_ChatServer.mb_displayAppend("客户端: " + m);
this.sleep(1000);
} while(!J_ChatServer.mb_isEndSession( m ));// do-while循环结束
}catch(Exception e){
}


}




}


  • 打赏
  • 举报
回复
给你写个服务器多客户多线程通讯的方式:
while(true){
socket=serverSocket.accept();
分配一个线程:如 new 线程名(socket);
}
然后将事件交给线程来处理就行了
abc130314 2009-05-17
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 JAVALover4444444444 的回复:]
给你写个服务器多客户多线程通讯的方式:
while(true){
socket=serverSocket.accept();
分配一个线程:如 new 线程名(socket);
}
然后将事件交给线程来处理就行了
[/Quote]
新得到一个新的socket,就可以和一个新的客户端通信。
jiang5495 2009-05-17
  • 打赏
  • 举报
回复
这是常识性错误。服务器只用一个端口就可以与多个客户端通信。

如何用一个端口去实现呢???
能不能给点思路
abc130314 2009-05-17
  • 打赏
  • 举报
回复
每次都是服务器先运行,那么端口就已经确定了,那么就只能与一个客户端进行通信,
这是常识性错误。服务器只用一个端口就可以与多个客户端通信。
jiang5495 2009-05-17
  • 打赏
  • 举报
回复
大家帮忙看看啊,谢了!!!
1、本课程是一个干货课程,主要讲解如何封装服务器底层,使用Tcp/ip长连接,IDE使用vs2019 c++开发以及使用c++11的一些标准,跨平台windows和linux,服务器性能高效,单服务器压力测试上万无压力,服务器框架是经历过上线产品的验证,框架简单明了,不熟悉底层封装的人,半个小时就能完全掌握服务器框架上手写业务逻辑。2、本课程是一个底层服务器框架教程,主要是教会学员在windows或linux下如何封装一个高效的,避免踩坑的商业级框架,服务器底层使用初始化即开辟内存的技术,使用内存池,服务器运行期间内存不会溢出,非常稳定,同时服务器使用自定义哈希hashContainer,在处理新的连接,新的数据,新的封包,以及解包,发包,粘包的过程,哈希容器性能非常高效,增、删、查、改永远不会随着连接人数的上升而降低性能,增、删、查、改的复杂度永远都是恒定的O(1)。3、服务器底层封装没有使用任何第三方网络库以及任何第三方插件,自由度非常的高,出了任何BUG,你都有办法去修改,查找问题也非常方便,在windows下使用iocp,linux下使用epoll.4、讲解c++纯客户端,主要用于服务器之间通信,也就是说你想搭建多层结构的服务器,服务器与服务器之间使用socket通信。还可以使用c++客户端做压力测试,开辟多线程连接服务器,教程提供了压力测试,学员可以自己做压力测试服务器性能。5、赠送ue4和unity3d通信底层框架以及多人交互demo,登录,注册,玩家离开,同步主要是教会学员服务器与客户端如何交互。6、赠送c++连接mysql数据库框架demo,登录,注册,玩家离开数据持久化.7、服务器教程使用自定义通信协议,同时也支持protobuf,选择权在开发者自己手里,想用什么协议都可以,自由度高。8、服务器教程使用手动敲代码逐句讲解的方式开展教学课程。非喜勿喷,谢谢大家。9、服务器教程提供源码,大家可以在平台提供的地址下载或者联系我,服务器使用c++11部分标准,std::thread,条件变量,线程锁,智能指针等,需要学员具备一定c++知识,购买前请慎重考虑。

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧