java网络编程基础

前言


  通过网络进行数据传输时,一般使用TCP/UDP进行数据传输。但是两个的区别就是TCP可靠,UDP不可靠。两个的共同之处就是都需要建立socket套接字,将IP地址和端口port进行绑定。但是服务器和客户端的socket是有点区别的,服务器端需要显示的指定端口号,以便进行数据监听;而客户端只需要指定IP就行,端口号则由操作系统来分配。

基础类


 

(1) InetAddress类

  该类就是表示互联网中的IP地址,常用的方法有:

  • getByName(String host) 静态方法,给定主机名来获取IP地址对象
  • getHostAddress()   获取主机的ip地址

(2) InetSocketAddress类

  这个类一看就可socket有关,他就是用来创建socket套接字,将ip地址和端口进行绑定,主要的用法就是其构造器:

  •  InetSocketAddress(InetAddress addr, int port)  //如果addr等于null,则表示绑定本机的所有IP
  •  InetSocketAddress(String hostname,  int port)

服务器端套接字


 

  这里只简述TCP套接字,我们先看看如果如何写一个简单的服务器,这里先用linux C来实现。

#include "unp.h"
#include <time.h>

int main(int argc, char** argv){
    int listenfd, connfd;
    socketlen_t len;
    struct sockaddr_in servaddr, cliaddr;
    char buff[MAXLINE];
    time_t ticks;

    //选择协议族创建套接字3,这里是TCP族
    listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    //将本机上所有的IP的都进行注册
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    //指定监听的端口号
    servaddr.sin_port = htons(31);
    //将赋值好结构体seraddr绑定到套接字上
    Bind(listenfd, (SA *)&servaddr, sizeof(servaddr));
    //打开端口监听,第二个参数表示未完成链接的最大个数(正在进行SYN传输)
    Listen(listenfd, LISTENQ);
    for(;;){
        len = sizeof(cliaddr);
        connfd = Accept(listenfd, (SA *)&cliaddr, &len);
        Write(connfd, buff, strlen(buff));
        Close(connfd);
    }
}

可以看到在用C实现一个TCP服务器时比较复杂,而java就相对简单一些。

  • java服务器
package com.dy.xidian.net;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8888);
        Socket socket = server.accept();
        String msg = "欢迎使用";
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                socket.getOutputStream()));
        bw.write(msg);
        bw.flush();
        bw.close();
    }
}
  • java客户端
package com.dy.xidian.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
    public static void main(String[] args) throws UnknownHostException,
            IOException {
        Socket client = new Socket("localhost", 8888);
        BufferedReader br = new BufferedReader(new InputStreamReader(
                client.getInputStream()));
        String echo = br.readLine();
        System.out.println(echo);
    }
}

分析java套接字


 

  ServerSocket server = new ServerSocket(8888); 

我们先看ServerSocket实现方式,其调用了另一个套接字:

public ServerSocket(int port) throws IOException {
        this(port, 50, null);
    }

ServerSocket的重载函数,主要是用InetSocketAddress创建套接字并进行通过bind进行绑定

 public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
        setImpl();
        if (port < 0 || port > 0xFFFF)
            throw new IllegalArgumentException(
                       "Port value out of range: " + port);
        if (backlog < 1)
          backlog = 50;
        try {
            bind(new InetSocketAddress(bindAddr, port), backlog);
        } catch(SecurityException e) {
            close();
            throw e;
        } catch(IOException e) {
            close();
            throw e;
        }
    }

在进行bind操作时,同时也调用的监听函数,这里只显示一部分

public void bind(SocketAddress endpoint, int backlog) throws IOException {
        //TODO
        try {
            SecurityManager security = System.getSecurityManager();
            if (security != null)
                security.checkListen(epoint.getPort());
            getImpl().bind(epoint.getAddress(), epoint.getPort());
            getImpl().listen(backlog);
            bound = true;
        } 
       // TODO
 }

 总结


 

  通过上面的观察,我们可以发现虽然java在进行网络编程中的代码相对比较简单,但是其内部的整个流程和C是一样的。对服务器而言都需要经历:创建套接字---绑定套接字----监听端口----接受请求。这个值得注意的是listen会将建立好的套接字(刚完成三次握手)放到一个缓冲队列中,而accept会从缓冲队列中取。由于缓冲队列可能满也可能空,所以listen会出现阻塞(表现为拒绝客户端的链接)。当缓冲区空的时候accept则会阻塞。

原文地址:https://www.cnblogs.com/xidongyu/p/5498354.html