Java socket经典示例_齊帥的博客-程序员宝宝

技术标签: Java  java  import  string  通讯  服务器  socket  

事实上网络编程简单的理解就是两台计算机相互通讯数据而已.对于程序员而言,去掌握一种编程接口并使用一种编程模型相对就会显得简单的多了.Java SDK提供一些相对简单的Api来完成这些工作.Socket就是其中之一.对于Java而言.这些Api存在与java.net 这个包里面.因此只要导入这个包就可以准备网络编程了. 
    网络编程的基本模型就是客户机到服务器模型.简单的说就是两个进程之间相互通讯,然后其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置.并去建立两者之间的联系..然后完成数据的通讯就可以了.这里提供固定位置的通常称为服务器,而建立联系的通常叫做客户端.基于这个简单的模型,就可以进入网络编程啦.
     Java对这个模型的支持有很多种Api.而这里我只想介绍有关Socket的编程接口.对于Java而言已经简化了Socket的编程接口.首先我们来讨论有关提供固定位置的服务方是如何建立的.Java提供了ServerSocket来对其进行支持.事实上当你创建该类的一个实力对象并提供一个端口资源你就建立了一个固定位置可以让其他计算机来访问你.

ServerSocket server=new ServerSocket(6789);

这里稍微要注意的是端口的分配必须是唯一的.因为端口是为了唯一标识每台计算机唯一服务的.另外端口号是从0~65535之间的,前1024个端口已经被Tcp/Ip 作为保留端口,因此你所分配的端口只能是1024个之后的.好了.我们有了固定位置.现在所需要的就是一根连接线了.该连接线由客户方首先提出要求.因此Java同样提供了一个Socket对象来对其进行支持.只要客户方创建一个Socket的实例对象进行支持就可以了.

Socket client=new Socket(InetAddress.getLocalHost(),5678);

客户机必须知道有关服务器的IP地址.对于着一点Java也提供了一个相关的类InetAddress 该对象的实例必须通过它的静态方法来提供.它的静态方法主要提供了得到本机IP 和通过名字或IP直接得到InetAddress的方法.
    好了.上面的方法基本可以建立一条连线让两台计算机相互交流了.可是数据是如何传输的呢?事实上I/O操作总是和网络编程息息相关的.因为底层的网络是继续数据的.除非远程调用,处理问题的核心在执行上.否则数据的交互还是依赖于IO操作的.所以你也必须导入java.io这个包.java的IO操作也不复杂.它提供了针对于字节流和Unicode的读者和写者,然后也提供了一个缓冲用于数据的读写.
BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out=new PrintWriter(server.getOutputStream());
    上面两句就是建立缓冲并把原始的字节流转变为Unicode可以操作.而原始的字节流来源于Socket的两个方法.getInputStream()和getOutputStream()方.分别用来得到输入和输出.那么现在有了基本的模型和基本的操作工具.我们可以做一个简单的Socket例程了.
服务方:
import java.io.*;
import java.net.*;

public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);
Socket client=server.accept();
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break;
}
client.close();
}
}

这个程序的主要目的在于服务器不断接收客户机所写入的信息只到.客户机发送"End"字符串就退出程序.并且服务器也会做出"Receive"为回应.告知客户机已接收到消息.

客户机代码:
import java.net.*;
import java.io.*;

public class Client{
static Socket server;

public static void main(String[] args)throws Exception{
server=new Socket(InetAddress.getLocalHost(),5678);
BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out=new PrintWriter(server.getOutputStream());
BufferedReader wt=new BufferedReader(new InputStreamReader(System.in));

while(true){
String str=wt.readLine();
out.println(str);
out.flush();
if(str.equals("end")){
break;
}
System.out.println(in.readLine());
}
server.close();
}
}

客户机代码则是接受客户键盘输入,并把该信息输出,然后输出"End"用来做退出标识.

这个程序只是简单的两台计算机之间的通讯.如果是多个客户同时访问一个服务器呢?你可以试着再运行一个客户端,结果是会抛出异常的.那么多个客户端如何实现呢?

其实,简单的分析一下,就可以看出客户和服务通讯的主要通道就是Socket本身.而服务器通过accept方法就是同意和客户建立通讯.这样当客户建立Socket的同时.服务器也会使用这一根连线来先后通讯.那么既然如此只要我们存在多条连线就可以了.那么我们的程序可以变为如下:

服务器:

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

public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
Socket client=server.accept();
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break;
}
client.close();
}
}
}

这里仅仅只是加了一个外层的While循环.这个循环的目的就是当一个客户进来就为它分配一个Socket直到这个客户完成一次和服务器的交互,这里也就是接受到客户的"End"消息.那么现在就实现了多客户之间的交互了.但是.问题又来了.这样做虽然解决了多客户,可是是排队执行的.也就是说当一个客户和服务器完成一次通讯之后下一个客户才可以进来和服务器交互.无法做到同时服务.那么要如何才能同时达到既能相互之间交流又能同时交流呢?很显然这是一个并行执行的问题了.所以线程是最好的解决方案.
那么下面的问题是如何使用线程.首先要做的事情是创建线程并使得其可以和网络连线取得联系.然后由线程来执行刚才的操作.要创建线程要么直接继承Thread要么实现Runnable接口,要建立和Socket的联系只要传递引用就可以了.而要执行线程就必须重写run方法.而run方法所做的事情.就是刚才单线程版本main所做的事情.因此我们的程序变成了这样:
import java.net.*;
import java.io.*;

public class MultiUser extends Thread{
private Socket client;

public MultiUser(Socket c){
this.client=c;
}

public void run(){
try{
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
//Mutil User but can't parallel
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break;
}
client.close();
}catch(IOException ex){
}finally{

}
}

public static void main(String[] args)throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
//transfer location change Single User or Multi User
MultiUser mu=new MultiUser(server.accept());
mu.start();
}
}
}

我的类直接从Thread类继承了下来.并且通过构造函数传递引用和客户Socket建立了联系.这样每个线程就有了.一个通讯管道.同样我们可以填写run方法.把之前的操作交给线程来完成.这样多客户并行的Socket就建立起来了.

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mark_qi/article/details/7399390

智能推荐

ACI Flux Estimator MACRO Definition_aci_fe_happy_baymax的博客-程序员宝宝

/* =================================================================================File name: ACI_FE.H (IQ version)===================================================================================*/#ifndef ACI_FE_H#define ACI_FE_Htypedef st

关于struct中的static变量_c语言结构体static_LuckyDan61的博客-程序员宝宝

先来看一段程序:#include typedef struct with_static{    int a;    static const int b = 1;}with_static;int main(){    struct with_static test1;    struct with_static test2;    tes

linq 的join多表和select使用,let变量_Marzlam的博客-程序员宝宝

join 分为inner join,left join ,cross joinselect 分为select 和selectmany通俗的来说 查询 有 平面查询和层次查询,关联有内关联和外关联所以说根据项目中实际运用的情况,来选择是 inner join 还是 left join 而且是平面还是层次inner join :var query = from a in tb1 ...

Chrome扩展及应用开发 入门笔记(二)跨域请求_多则惑少则明的博客-程序员宝宝

manifest.json:文件可以告诉Chrome关于这个扩展的相关信息,它是整个扩展的入口,也是Chrome扩展必不可少的部分注:Google的官方文档中对于扩展和应用给出了两个不同的Manifest介绍界面,这是因为有些属性只能由扩展使用,而有些属性只能由应用使用。如果这两者同时出现在同一个Manifest文件中,就会使Chrome困惑,不知是按照扩展对待这个程序还是

浅析Jsp和Servlet的区别与联系_chiran9291的博客-程序员宝宝

JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP技术有点类似ASP技术,它是在传统的网页HTML(标准通用标记语言的子集)文件(*...

eXtremeDB在各行各业中的应用案例_weixin_34335458的博客-程序员宝宝

这个是eXtremeDB应用在金融领域,大连交易所是中国最大的此类交易所之一。在大连商品交易所的交易平台中,McObject公司的64位内存数据库eXtremeDB-64每天管理着完成20万宗交易所需要的买、卖及其他实时信息。大连商品交易所采用eXtremeDB-64位版本对高吞吐率进行优化的数据库事务机制 极大提升了金融系统交易平台的健壮性。 如今交易量和行情数据正在飞...

随便推点

自然语言处理(3):词性标注_自然语言 词性_郝伟博士的博客-程序员宝宝

文章目录1 概述2 词性标注难点3 词性标注算法3.1 基于字符串匹配的字典查找算法3.2 基于统计的词性标注算法4 jieba词性标注原理4.1 准备工作4.2 遍历语句,进行分词和词性标注4.3 未登录词,HMM隐马尔科夫模型处理5 总结转载来源:https://blog.csdn.net/u013510838/article/details/819071211 概述词性标注在自然语言处理中也属于基础性的模块,为句法分析、信息抽取等工作打下基础。和分词一样,中文词性标注也存在着很多难点,比如一词多

【算法设计与分析基础】22、最优二叉查找树_weixin_30596343的博客-程序员宝宝

package cn.xf.algorithm.ch08DynamicProgramming;import java.util.Arrays;import org.junit.Test;import cn.xf.algorithm.ch08DynamicProgramming.vo.ResultVo;/** * 最优二叉树问题 * * 思路:根据最...

linux 批量处理 dos2unix_-exec dos2unix_whatday的博客-程序员宝宝

在 windows 下编辑过的文件一般都会被保存为 dos 格式, 而 mac os x 和 *nix 类系统一般都是使用 unix 格式,在windows下编辑过的文件在*nix下打开,会被加上^M, 然后造成程序出问题。所以需要将文件的格式从dos转换成unix.可以使用的工具是dos2unix,使用命令如下:因为文件的数量太大,所以需要批量的来导。这里就可以使用fin...

GBDT、Xgb、Lgb对比以及常见面试题_xgb,lgb,gbdt面试常见问题_Sigyc的博客-程序员宝宝

GBDT、Xgb、Lgb对比以及常见面试题GBDT特点正则化Xgb特点正则化Lgb常见面试题RF与GBDT之间的区别Xgb与GBDT的区别Lgb与Xgb的区别之前写了一点RF的东西,作为决策树+bagging的模型自然经常会被拉出来和决策树+boosting的模型进行对比;而GBDT、Xgb、Lgb一系列的产物正式这种思路加上一些改进的工程产物,所以就一起放出来对比说明了。GBDT特点GBDT 是梯度提升树(Gradient Boosting Decison Tree)的简称,GBDT 通过多轮迭代

Gradle digest_weixin_34303897的博客-程序员宝宝

task类型copytask copyFiles(type: Copy) { from 'resources' into 'target' include '**/*.xml', '**/*.txt', '**/*.properties'}jarapply plugin: 'java'task customJar(type:...

推荐文章

热门文章

相关标签