网络编程TCP通信

举报
xcc-2022 发表于 2022/07/21 22:25:51 2022/07/21
【摘要】 目录背景知识程序用到的一些类InetAddress 类ServerSocket 类(服务端)Socker 类(客户端)示例代码功能说明使用说明责任声明代码本体背景知识TCP 是面向连接的可靠的字节流的传输。TCP 通信模型是典型的客户机-服务器模型。通信双方的通信模型如下:TCP 通信的双方使用 Socket 进行通信。通信一方的 IP 地址及其端口号,合称为一个Socket,通信双方各自的...


背景知识

TCP 是面向连接的可靠字节流的传输。TCP 通信模型是典型的客户机-服务器模型。
通信双方的通信模型如下:

  • TCP 通信的双方使用 Socket 进行通信。
    • 通信一方的 IP 地址及其端口号,合称为一个Socket,通信双方各自的 Socket,唯一地标识了本次双方的通信。
    • Socket 中的 IP 地址唯一标识了一台主机,而端口号则唯一标识了该通信主机上的一个程序(或进程)。

程序用到的一些类

InetAddress 类

方法摘录如下:(参见java jdk8官方文档)

boolean equals(Object obj)
Compares this object against the specified object.
byte[] getAddress()
Returns the raw IP address of this InetAddress object.
static InetAddress[] getAllByName(String host)
Given the name of a host, returns an array of its IP addresses, based on the configured name service on the system.
static InetAddress getByAddress(byte[] addr)
Returns an InetAddress object given the raw IP address .
static InetAddress getByAddress(String host, byte[] addr)
Creates an InetAddress based on the provided host name and IP address.
static InetAddress getByName(String host)
Determines the IP address of a host, given the host’s name.
String getCanonicalHostName()
Gets the fully qualified domain name for this IP address.
String getHostAddress()
Returns the IP address string in textual presentation.
String getHostName()
Gets the host name for this IP address.
static InetAddress getLocalHost()
Returns the address of the local host.
static InetAddress getLoopbackAddress()
Returns the loopback address.
int hashCode()
Returns a hashcode for this IP address.
boolean isAnyLocalAddress()
Utility routine to check if the InetAddress in a wildcard address.
boolean isLinkLocalAddress()
Utility routine to check if the InetAddress is an link local address.
boolean isLoopbackAddress()
Utility routine to check if the InetAddress is a loopback address.
boolean isMCGlobal()
Utility routine to check if the multicast address has global scope.
boolean isMCLinkLocal()
Utility routine to check if the multicast address has link scope.
boolean isMCNodeLocal()
Utility routine to check if the multicast address has node scope.
boolean isMCOrgLocal()
Utility routine to check if the multicast address has organization scope.
boolean isMCSiteLocal()
Utility routine to check if the multicast address has site scope.
boolean isMulticastAddress()
Utility routine to check if the InetAddress is an IP multicast address.
boolean isReachable(int timeout)
Test whether that address is reachable.
boolean isReachable(NetworkInterface netif, int ttl, int timeout)
Test whether that address is reachable.
boolean isSiteLocalAddress()
Utility routine to check if the InetAddress is a site local address.
String toString()
Converts this IP address to a String.

ServerSocket 类(服务端)

构造器:
ServerSocket()
Creates an unbound server socket.
ServerSocket(int port)
Creates a server socket, bound to the specified port.
ServerSocket(int port, int backlog)
Creates a server socket and binds it to the specified local port number, with the
specified backlog.
ServerSocket(int port, int backlog, InetAddress bindAddr)
Create a server with the specified port, listen backlog, and local IP address to bind to.

我觉得比较常用的是这几个方法:
Socket accept()
Listens for a connection to be made to this socket and accepts it.
void bind(SocketAddress endpoint)
Binds the ServerSocket to a specific address (IP address and port number).
void bind(SocketAddress endpoint, int backlog)
Binds the ServerSocket to a specific address (IP address and port number).
void close()
Closes this socket.

Socker 类(客户端)

构造器有很多种形式,方法也是。。。
太长了我就不贴了,有需要的直接去查文档也比在这翻文章快。。。

示例代码

功能说明

该代码模拟一个在控制台实现的简易多人聊天室。

使用说明

  • 使用时先运行服务端线程,再运行客户端线程。
  • 如需多人聊天,可将Client多复制粘贴几遍(改改名字),一个类代表一个聊天对象

责任声明

虽然代码是实验指导书上的 ,但我不是直接复制粘贴上去,而是看完一遍然后再打一遍,贴的是我自己打的版本。
要是发现有误,是我的问题。
老师写的代码质量可是杠杠滴!

代码本体

服务端

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

//本案例中服务端无法直接发送消息给客户端,而是将一个客户端的消息发送给所有客户端
public class SimpleServer {
    //限定群聊人数为100,保存所有客户端socket信息
    public static Socket [] group=new Socket[100];

    public static void main(String[] args) throws Exception{
        ServerSocket ss=new ServerSocket(10002);
        System.out.println("----服务端服务启动!----");
        //记录当前用户数量,不能超过group数组长度上限
        int cnt=0;
        //循环接收用户消息
        while(true){
            //每接受一个用户请求,产生一个新的socket
            Socket socket=ss.accept();
            group[cnt]=socket;
            cnt++;
            System.out.println("----服务已连接!----");
            new ServerThread(socket,group).start();
        }
    }
}

class ServerThread extends Thread{
    Socket client;
    Socket[] group;
    int num;
    BufferedReader br;
    public ServerThread(Socket client,Socket[] group)throws Exception{
        super();
        this.client=client;
        this.group=group;
        br=new BufferedReader(new InputStreamReader(this.client.getInputStream()));
    }

    public void run(){
        try{
            String content=null;
            while(true){
                if((content=br.readLine())!=null){
                    //把消息发送至各客户端
                    for (int i = 0; i < group.length; i++) {
                        if(group[i]!=null&&client!=group[i]){
                            PrintWriter pw=new PrintWriter(group[i].getOutputStream(),true);
                            pw.println(content);
                        }
                    }
                    //在服务端控制台也显示该信息
                    System.out.println(content);
                }
            }
        }catch(IOException e){
            e.printStackTrace();
        }
    }
}

客户端

import java.io.*;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws Exception{
        //创建连接到本机,端口号为10002的socket
        Socket client=new Socket("127.0.0.1",10002);
        //这里暂时使用命令行界面,有需要再换成GUI或前端
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        System.out.println("系统消息:请输入您的昵称:");
        String name=br.readLine();
        System.out.println("系统消息:欢迎 "+name+" 加入聊天室!");
        new ClientThread(client,name).start();
        InputStream is=client.getInputStream();
        BufferedReader acceptMsg=new BufferedReader(new InputStreamReader(is));
        while(true){
            //循环接收消息,cpu会在main和clientThread线程之间来回切换
            String msg=acceptMsg.readLine();
            //将收到的信息显示在控制台上,后期可以修改为显示到其他地方
            System.out.println(msg);
        }
    }
}

class ClientThread extends Thread{
Socket client;
String name;
public ClientThread(Socket client,String name){
    this.client=client;
    this.name=name;
}

public void run(){
    try{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw=new PrintWriter(client.getOutputStream(),true);
        while(true) {
            String msg = br.readLine();
            msg = name + ":" + msg;
            pw.println(msg);
        }
    }catch(IOException e){
        e.printStackTrace();
    }
}
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。