【Java网络】Socket 单一


对于即时类应用或者即时类的游戏,HTTP协议很多时候无法满足于我们的需求。这会,Socket对于我们来说就非常实用了。下面是本次学习的笔记。主要分异常类型、交互原理、Socket、ServerSocket、多线程这几个方面阐述。

 

异常类型
在了解Socket的内容之前,先要了解一下涉及到的一些异常类型。以下四种类型都是继承于IOException,所以很多之后直接弹出IOException即可。
UnkownHostException:      主机名字或IP错误
ConnectException:        服务器拒绝连接、服务器没有启动、(超出队列数,拒绝连接)
SocketTimeoutException:      连接超时
BindException:          Socket对象无法与制定的本地IP地址或端口绑定


1、socket和serverSocket通信简单介绍如下,注意客户端与服务器端是怎么交换数据的

 

 

Socket
构造函数

Socket()

Socket(InetAddress address, int port)throws UnknownHostException, IOException
Socket(InetAddress address, int port, InetAddress localAddress, int localPort)throws IOException
Socket(String host, int port)throws UnknownHostException, IOException
Socket(String host, int port, InetAddress localAddress, int localPort)throws IOException
 
除去第一种不带参数的之外,其它构造函数会尝试建立与服务器的连接。如果失败会抛出IOException错误。如果成功,则返回Socket对象。
InetAddress是一个用于记录主机的类,其静态getHostByName(String msg)可以返回一个实例,其静态方法getLocalHost()也可以获得当前主机的IP地址,并返回一个实例。Socket(String host, int port, InetAddress localAddress, int localPort)构造函数的参数分别为目标IP、目标端口、绑定本地IP、绑定本地端口。
 
Socket方法
getInetAddress();      远程服务端的IP地址
getPort();          远程服务端的端口
getLocalAddress()      本地客户端的IP地址
getLocalPort()        本地客户端的端口
getInputStream();     获得输入流
getOutStream();      获得输出流
值得注意的是,在这些方法里面,最重要的就是getInputStream()和getOutputStream()了。
 
Socket状态
isClosed();            //连接是否已关闭,若关闭,返回true;否则返回false
isConnect();      //如果曾经连接过,返回true;否则返回false
isBound();            //如果Socket已经与本地一个端口绑定,返回true;否则返回false
如果要确认Socket的状态是否处于连接中,下面语句是很好的判断方式。
boolean isConnection=socket.isConnected() && !socket.isClosed();   //判断当前是否处于连接
半关闭Socket
很多时候,我们并不知道在获得的输入流里面到底读多长才结束。下面是一些比较普遍的方法:
  • 自定义标识符(譬如下面的例子,当受到“bye”字符串的时候,关闭Socket)
  • 告知读取长度(有些自定义协议的,固定前几个字节表示读取的长度的)
  • 读完所有数据
  • 当Socket调用close的时候关闭的时候,关闭其输入输出流

ServerSocket
构造函数
ServerSocket()throws IOException
ServerSocket(int port)throws IOException
ServerSocket(int port, int backlog)throws IOException
ServerSocket(int port, int backlog, InetAddress bindAddr)throws IOException
 
注意点:
1. port服务端要监听的端口;backlog客户端连接请求的队列长度;bindAddr服务端绑定IP
2. 如果端口被占用或者没有权限使用某些端口会抛出BindException错误。譬如1~1023的端口需要管理员才拥有权限绑定。
3. 如果设置端口为0,则系统会自动为其分配一个端口;
4. bindAddr用于绑定服务器IP,为什么会有这样的设置呢,譬如有些机器有多个网卡。
5. ServerSocket一旦绑定了监听端口,就无法更改。ServerSocket()可以实现在绑定端口前设置其他的参数。
 
单线程ServerSocket举例:
public void service(){
    while(true){
        Socket socket=null;
        try{
            socket=serverSocket.accept();//从连接队列中取出一个连接,如果没有则等待
            System.out.println("新增连接:"+socket.getInetAddress()+":"+socket.getPort());
            ...//接收和发送数据
        }catch(IOException e){e.printStackTrace();}finally{
            try{
                if(socket!=null) socket.close();//与一个客户端通信结束后,要关闭Socket
            }catch(IOException e){e.printStackTrace();}
        }
    }
}



2、模拟qq聊天功能,实现客户端与服务器(一对一)的聊天功能

服务器端代码:

package socketDemo;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class chatServer {

	/**
	 * @param 
	 * 模拟qq聊天功能,实现客服端和服务器(一对一)聊天功能,客户端首先发起聊天,
	 * 输入的内容在客户端和服务器端同时显示,
	 * 然后服务器端也可以输入信息,同样信息也在客户端和服务器显示
	 * 
	 */
	private int port=8099;
	public chatServer(){}
	//创建指定端口的服务器
	public chatServer(int port){
	this.port=port;
	}
	//提供服务
	public void service(){
		try{//建立服务器连接
			ServerSocket server= new ServerSocket(port);
			//等待客户连接
			Socket socket=server.accept();
			try{
				//读取客户端传过来信息的DataInputStrem
				DataInputStream in= new DataInputStream(socket.getInputStream());
				//向客户端传过来信息的DataOutputStram
				DataOutputStream out= new DataOutputStream(socket.getOutputStream());
				//获取控制台输入的Scanner:
				Scanner scanner = new Scanner(System.in);
				while(true){
					//读取来自客户端的信息
					String accept= in.readUTF();
					System.out.println(accept);
					String send=scanner.nextLine();
					System.out.println("服务器:"+send);
					//把服务器端的输入打给客户端
					out.writeUTF("服务器:"+send);
					
				}
			}finally{
				socket.close();
			}
			
		
		}catch(IOException e){
			e.printStackTrace();
		}
	}


客户端代码:

package socketDemo;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

public class chatClient {

	/**
	 * @param args
	 * 注意用到的输入输出流DAtaInputStram和DataOutputStram,成对出现,最好用字节流
	 */
	
	//客户端
	private String host="localhost";
	private int port=8099;//默认连接到端口8189
	public chatClient(){
		
	}
  //连接到指定的主机和端口
	public chatClient(String host,int port){
		this.host=host;
		this.port=port;
	}
	public void chat(){
		try{//连接到服务器
			Socket socket=new Socket(host,port);
			try{
				//读取服务器端传来的信息的DataInputStream
				DataInputStream in = new DataInputStream(socket.getInputStream());
				//向服务器发送信息的DataOutputStream
				DataOutputStream out= new DataOutputStream(socket.getOutputStream());
				//装饰标准输入流,用于控制台输入
				Scanner scanner= new Scanner(System.in);
				
				while(true){
				String send=scanner.nextLine();
				System.out.println("客户端"+send);
				//把从控制台得到的信息传送给服务器
				out.writeUTF("客户端:"+send);
				//读取来自服务器的信息
				String accept=in.readUTF();
				System.out.println(accept);
				
				}
				}finally{
					socket.close();
				}
			}catch(IOException e){
				e.printStackTrace();
			}
			
		}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
new chatClient().chat();
	}

}






  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值