socket多线程java
1. java socket客户端还用多线程吗
服务端要同时为很多客户工作的话,简单的设计就是使用多线程,每个线程为一个客户工作。客户端通常不需要特别多的线程,但是一般也需要一个工作线程负责和服务端的协议处理,一个界面的线程,否则如果网络阻塞,用户的体验会很不好(界面总是卡壳)。当然简单学习的话,客户端用单线程也是可以的。
例子代码很多Java编程的书里都有,可以在网上搜索一下。推荐还是去下载一本Java网络编程的电子书吧,不然光看实例源代码,一些基本概念和处理方法不太容易明白为什么要这样做的。
2. java socket多线程的问题可以多个线程使用同一个socket吗
可以写个demo试一下啊,应该是可以的,socket接收到的消息只能被其中一个线程接收。线程1 和2 接受到的肯定不是同一个消息。会有先后之分。看你怎么控制。比如从接收的消息是ABCD,那么这相当于一个资源。线程1和2在这里拿消息,拿到之后,socket里面就少了,比如线程1拿到AB,线程2拿到CD
3. java一个Socket连接多线程是否能操作两个读取流
可以啊 ,不过需要新建两个实现Runnable 借口的类,重写run方法,一个实现读取,另一个实现输出的功能。再用两条线程分别操作这两个方法。
4. 用Java的socket编程实现c/s结构程序
今天太晚了,改天给你做一个,记得提醒我,这个如果只是要个简单的,我半个小时就搞定了
给我个邮箱
现在给贴出我的代码: 整个结构分两个工程
1。服务端工程NioServer.java: 采用nio 方式的异步socket通信,不仅可以实现你的服务器还可以让你多学习一下什么是nio
2。客户端工程UserClient.java: 采用Swing技术画了一个简单的UI界面,比较土,原因是我没那么多时间去设计界面,你需要的话可以自己去修改得漂亮点,相信不难
现在贴工程1:
package com.net;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class NioServer {
public static final int SERVERPORT=5555;
public static final String USERNAME="wangrong";
public static final String PASSWORD="123456";
public static final String ISACK="ACK";
public static final String ISNAK="NAK!";
// Selector selector;//选择器
// SelectionKey key;//key。 一个key代表一个Selector 在NIO通道上的注册,类似主键;
// //取得这个Key后就可以对Selector在通道上进行操作
private ByteBuffer echoBuffer = ByteBuffer.allocate( 1024 );// 通道数据缓冲区
public NioServer(){
}
public static void main(String[] args) throws IOException {
NioServer ns=new NioServer();
ns.BuildNioServer();
}
public void BuildNioServer() throws IOException{
/////////////////////////////////////////////////////////
///////先对服务端的ServerSocket进行注册,注册到Selector ////
/////////////////////////////////////////////////////////
ServerSocketChannel ssc = ServerSocketChannel.open();//新建NIO通道
ssc.configureBlocking( false );//使通道为非阻塞
ServerSocket ss = ssc.socket();//创建基于NIO通道的socket连接
//新建socket通道的端口
ss.bind(new InetSocketAddress("127.0.0.1",SERVERPORT));
Selector selector=Selector.open();//获取一个选择器
//将NIO通道选绑定到择器,当然绑定后分配的主键为skey
SelectionKey skey = ssc.register( selector, SelectionKey.OP_ACCEPT );
////////////////////////////////////////////////////////////////////
//// 接收客户端的连接Socket,并将此Socket也接连注册到Selector ////
///////////////////////////////////////////////////////////////////
while(true){
int num = selector.select();//获取通道内是否有选择器的关心事件
if(num<1){continue; }
Set selectedKeys = selector.selectedKeys();//获取通道内关心事件的集合
Iterator it = selectedKeys.iterator();
while (it.hasNext()) {//遍历每个事件
try{
SelectionKey key = (SelectionKey)it.next();
//有一个新联接接入事件,服务端事件
if ((key.readyOps() & SelectionKey.OP_ACCEPT)
== SelectionKey.OP_ACCEPT) {
// 接收这个新连接
ServerSocketChannel serverChanel = (ServerSocketChannel)key.channel();
//从serverSocketChannel中创建出与客户端的连接socketChannel
SocketChannel sc = serverChanel.accept();
sc.configureBlocking( false );
// Add the new connection to the selector
// 把新连接注册到选择器
SelectionKey newKey = sc.register( selector,
SelectionKey.OP_READ );
it.remove();
System.out.println( "Got connection from "+sc );
}else
//读客户端数据的事件,此时有客户端发数据过来,客户端事件
if((key.readyOps() & SelectionKey.OP_READ)
== SelectionKey.OP_READ){
// 读取数据
SocketChannel sc = (SocketChannel)key.channel();
int bytesEchoed = 0;
while((bytesEchoed = sc.read(echoBuffer))> 0){
System.out.println("bytesEchoed:"+bytesEchoed);
}
echoBuffer.flip();
System.out.println("limet:"+echoBuffer.limit());
byte [] content = new byte[echoBuffer.limit()];
echoBuffer.get(content);
String result=new String(content);
doPost(result,sc);
echoBuffer.clear();
it.remove();
}
}catch(Exception e){}
}
}
}
public void doPost(String str,SocketChannel sc){
boolean isok=false;
int index=str.indexOf('|');
if(index>0){
String name=str.substring(0,index);
String pswd=str.substring(index+1);
if(pswd==null){pswd="";}
if(name!=null){
if(name.equals(USERNAME)
&& pswd.equals(PASSWORD)
){
isok=true;
}else{
isok=false;
}
}else{
isok=false;
}
}else{
isok=false;
}
String result="";
if(isok){
result="ACK";
}else{
result="NAK!";
}
ByteBuffer bb = ByteBuffer.allocate( result.length() );
bb.put(result.getBytes());
bb.flip();
try {
sc.write(bb);
} catch (IOException e) {
e.printStackTrace();
}
bb.clear();
}
}
下面贴工程2
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class UserClient implements ActionListener{
JFrame jf;
JPanel jp;
JLabel label_name;
JLabel label_pswd;
JTextField userName;
JButton jb;
JPasswordField paswrd;
JLabel hintStr;
public UserClient (){
jf=new JFrame("XXX 登陆系统");
jp=new JPanel();
jf.setContentPane(jp);
jf.setPreferredSize(new Dimension(350,220));
jp.setPreferredSize(new Dimension(350,220));
jp.setBackground(Color.gray);
label_name=new JLabel();
label_name.setPreferredSize(new Dimension(150,30));
label_name.setText("请输入帐户(数字或英文):");
userName=new JTextField();
userName.setPreferredSize(new Dimension(150,30));
jp.add(label_name);
jp.add(userName);
label_pswd=new JLabel();
label_pswd.setPreferredSize(new Dimension(150,30));
label_pswd.setText("请输入密码:");
jp.add(label_pswd);
paswrd=new JPasswordField();
paswrd.setPreferredSize(new Dimension(150,30));
jp.add(paswrd);
jb=new JButton("OK");
jb.setPreferredSize(new Dimension(150,30));
jb.setText("确 定");
jb.addActionListener( this);
jp.add(jb);
hintStr=new JLabel();
hintStr.setPreferredSize(new Dimension(210,40));
hintStr.setText("");
hintStr.setForeground(Color.RED);
jp.add(hintStr);
jf.pack();
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private String name;
private String pswd;
public void actionPerformed(ActionEvent e) {
name=userName.getText().trim();
pswd=new String(paswrd.getPassword());
if(pswd==null){
pswd="";
}else{
pswd=pswd.trim();
}
if(name!=null && name.length()>0){
hintStr.setText("正在验证客户端,请稍候...");
start();
}
}
OutputStream os;
Socket s;
InputStream is;
public void start(){
//建立联网线程
new Thread(new Runnable(){
public void run() {
try {
s=new Socket("127.0.0.1",5555);
//写
os=s.getOutputStream();
os.write(name.getBytes());
os.write('|');//用户名与密码用"|"分隔
os.write(pswd.getBytes());
os.flush();
//读内容
Thread.sleep(1000);
is=s.getInputStream();
int len=is.available();
System.out.println("len:"+len);
byte[] bytes=new byte[len];
is.read(bytes);
String resut=new String(bytes);
System.out.println("resut:"+resut);
//TODO 这里通过返回结果处理
if(resut.equals("ACK")){
hintStr.setText("验证成功,欢迎光临!");
}else{
paswrd.setText(null);
hintStr.setText("用户名或密码错误,请重新输入");
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
// try {
// os.close();
// is.close();
// s.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
}).start();
}
public static void main(String[] args) {
new UserClient();
}
}
5. JAVA程序完成服务器和客户端的SOCKET通讯,要求服务器使用多线程接收和处理多个客户端访问请求
1. 客户端程序
import java.io.*;
import java.net.*;
public class TalkClient {
public static void main(String args[]) {
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")){
//若从标准输入读入的字符串为 "bye"则停止循环
os.println(readline);
//将从系统标准输入读入的字符串输出到Server
os.flush();
//刷新输出流,使Server马上收到该字符串
System.out.println("Client:"+readline);
//在系统标准输出上打印读入的字符串
System.out.println("Server:"+is.readLine());
//从Server读入一字符串,并打印到标准输出上
readline=sin.readLine(); //从系统标准输入读入一字符串
} //继续循环
os.close(); //关闭Socket输出流
is.close(); //关闭Socket输入流
socket.close(); //关闭Socket
}catch(Exception e) {
System.out.println("Error"+e); //出错,则打印出错信息
}
}
}
2. 服务器端程序
import java.io.*;
import java.net.*;
import java.applet.Applet;
public class TalkServer{
public static void main(String args[]) {
try{
ServerSocket server=null;
try{
server=new ServerSocket(4700);
//创建一个ServerSocket在端口4700监听客户请求
}catch(Exception e) {
System.out.println("can not listen to:"+e);
//出错,打印出错信息
}
Socket socket=null;
try{
socket=server.accept();
//使用accept()阻塞等待客户请求,有客户
//请求到来则产生一个Socket对象,并继续执行
}catch(Exception e) {
System.out.println("Error."+e);
//出错,打印出错信息
}
String line;
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//由Socket对象得到输入流,并构造相应的BufferedReader对象
PrintWriter os=newPrintWriter(socket.getOutputStream());
//由Socket对象得到输出流,并构造PrintWriter对象
BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//由系统标准输入设备构造BufferedReader对象
System.out.println("Client:"+is.readLine());
//在标准输出上打印从客户端读入的字符串
line=sin.readLine();
//从标准输入读入一字符串
while(!line.equals("bye")){
//如果该字符串为 "bye",则停止循环
os.println(line);
//向客户端输出该字符串
os.flush();
//刷新输出流,使Client马上收到该字符串
System.out.println("Server:"+line);
//在系统标准输出上打印读入的字符串
System.out.println("Client:"+is.readLine());
//从Client读入一字符串,并打印到标准输出上
line=sin.readLine();
//从系统标准输入读入一字符串
} //继续循环
os.close(); //关闭Socket输出流
is.close(); //关闭Socket输入流
socket.close(); //关闭Socket
server.close(); //关闭ServerSocket
}catch(Exception e){
System.out.println("Error:"+e);
//出错,打印出错信息
}
}}