Ⅰ java Socket编程和C++Socket编程有什么不同
Socket 是winsock里的原始套接字开发接口API,c++/java 他们是开发语言,晌冲而 socket 是一种通讯标准简称。首先,2者提供的接口不同(主要宴历歼是封装形式不同),java 本身不带socket通讯底层实现的,而是通过调用系统底层的winsock API 进行的二次封装,而c/c++ 的socket可以理解为 更接近 系统层面的winsock,所以c/c++ 的socket 可以提供 更多的底层扩展与控制。 其次,从语言上讲,用JAVA发开出来的socket程序 可以烂指在任何支持JAVA虚拟机上运行,不用修改任何代码。而 C/c++ 要根据系统特性进行适当的修改。
Ⅱ Java Socket初步详解
网络编程的基本模型就是客户机到服务器模型 简单的说就是两个进程之间相互通讯 然后其中一个必须提供一个固定的位置 而另一个则只需要知道这个固定的位置 并去建立两者之间的联系 然后完成数据的通讯就可以了 这里提供亩悉猜固定位置的通常称为服务器 而建立联系的通常叫做客户端 基于这个简单的模型 就可以进入网络编程啦
Java对这个模型的支持有很多种Api 而这里我只想介绍有关Socket的编程接口 对于Java而言已经简化了Socket的编程接口 首先我们来讨论有关提供固定位置的服务方是如何建立的 Java提供了ServerSocket来对其进行支持 事实上当你创建该类的一个实力对象并提供一个端口资源你就建立了一个固定位置可以让其他计算机来访问你 ServerSocket server=new ServerSocket( );这里稍微要注意的是端口的分配必须是唯一的 因为端口是为了唯一标识每台计算机唯一服务的 另外端口号是从 ~ 之间的 前 个端口已经被Tcp/Ip 作为保留端口 因此你所分配的端口只能是 个之后的 好了 我们有了固定位置 现在所需要的就是一根连接线了 该连接线由客户方首先提出要求 因此Java同样提供了一个Socket对象来对其进行支持 只要客户方创建一个Socket的实例对象进行支持就可以了 Socket client
=new Socket(InetAddress getLocalHost() );客户机必须知道有关服务器的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 *;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket( );
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 *;
import java io *;
public class Client{
static Socket server;
public static void main(String[] args)throws Exception{
server=new Socket(InetAddress getLocalHost() );
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 *;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket( );
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 *;
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( );
while(true){
//transfer location change Single User or Multi User
MultiUser mu=new MultiUser(server accept());
mu start();
}
}
}
lishixin/Article/program/Java/hx/201311/27013
Ⅲ 谁有java和C用socket通信的简单例子
这是用Java写的服务器的程序
importjava.net.*;
importjava.io.*;
publicclassServer{
privateServerSocketserver;
privateSocketclient;
publicServer(){
booleanflag=true;
try{
server=newServerSocket(8888);//端口
System.out.println("服务器正在等到客户端连接......");
while(flag){
client=server.accept();//阻塞
newServerThread(client).start();
}
server.close();
}catch(Exceptione){
}
}
publicstaticvoidmain(String[]args){
newServer();
}
{
privateSocketclientThread;
privatePrintStreamout;
privateBufferedReaderin;
privatebooleanflag=true;
publicServerThread(Socketclient){
this.clientThread=client;
System.out.println("主机与客户端成功建立连接,开始通讯!!");
}
publicvoidrun(){
try{
/*
*超时判断:设置超时时间300秒,中断连接或者300秒内客户端无回应信息则认为中断
*缺点便是必须把超时时间设置很长,否则客户端待机也认为超时处理,无法判断是否端口
*/
clientThread.setSoTimeout(300000);
out=newPrintStream(client.getOutputStream());
in=newBufferedReader(newInputStreamReader(client.getInputStream()));
while(flag){
Stringstr=in.readLine();//阻塞
System.out.println("客户端:"+str);
out.println("主机成功接收到您的信息!!");
}
client.close();
}catch(Exceptione){
//如果异常是连接异常,则输出连接断开
if(e.getMessage()=="Connectionreset"){
System.out.println("客户端已断开连接!!");
}
}
}
}
}
这是客户端的
importjava.net.*;
importjava.io.*;
publicclassClient{
privateSocketclient;
publicClient(){
InetAddressip;
try{
System.out.println("正在连接服务器......");
ip=InetAddress.getLocalHost();
Stringlocalip=ip.getHostAddress();
client=newSocket(localip,8888);//阻塞
BufferedReaderinput=newBufferedReader(newInputStreamReader(System.in));
BufferedReaderin=newBufferedReader(newInputStreamReader(client.getInputStream()));
PrintStreamout=newPrintStream(client.getOutputStream());;
booleanflag=true;
System.out.println("成功连接到主机,开始通讯!!");
while(flag){
System.out.printf("请输入信息:");
out.println(input.readLine());//阻塞
//判断是否与主机断开
if(isConnected()){
System.out.println("发生成功!!");
System.out.println("主机:"+in.readLine());
}else{
System.out.println("发生失败!!");
System.out.println("与服务器断开连接!!");
client.close();
break;
}
}
}catch(Exceptione){
System.out.println(e.getMessage());
}
}
//判断服务器是否断开的方法,
//通过OutputStream发送一段测试数据,如果发送失败就表示远端已经断开连接
//但会与正常的传送干扰,所以用sendUrgenData
publicbooleanisConnected(){
try{
client.sendUrgentData(0xFF);
returntrue;
}catch(Exceptione){
e.printStackTrace();
returnfalse;
}
}
publicstaticvoidmain(String[]args){
newClient();
}
}
Ⅳ 用Java Socket编程,实现简单的Echo功能
// 服务器
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("exit"))
break;
}
client.close();
}
}
}
// 客户端
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();
}
}
Ⅳ 用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();
}
}
Ⅵ Java网络编程从入门到精通(18):Socket类的getter和setter方法(2)
二 用于获得和设置Socket选项的getter和setter方法
Socket选择可以指定Socket类发送和接受数据的方式 在JDK *** 有 个Socket选择可以设置 这 个选项都定义在 SocketOptions接口中 定义如下
publicfinalstaticintTCP_NODELAY= x ; publicfinalstaticintSO_REUSEADDR= x ; publicfinalstaticintSO_LINGER= x ;publicfinalstaticintSO_TIMEOUT= x ;publicfinalstaticintSO_SNDBUF= x ;publicfinalstaticintSO_RCVBUF= x ;publicfinalstaticintSO_KEEPALIVE= x ;publicfinalstaticintSO_OOBINLINE= x ;
有趣的是 这 个选项除了第一个没在SO前缀外 其他 个选项都以SO作为前缀 其实这个SO就是Socket Option的缩写 因此 在Java中约定所有以SO为前缀的常量都表示Socket选项 当然 也有例外 如TCP_NODELAY 在Socket类中为每一个选项提供了一对get和set方法 分别用来获得和设置这些选项
TCP_NODELAY
publicbooleangetTcpNoDelay()(booleanon)throwsSocketException
在默认情况下 客户端向服务器发送数据时 会根据数据包的大小决定是否立即发送 当数据包中的数据很少时 如只有 个字节 而数据包的头却有几十个字节(IP头+TCP头)时 系统会在发送之前先将较小的包合并到软大的包后 一起将数据发送出去 在发送下一个数据包时 系统会等待服务器对前一个数据包的响应 当收到服务器的响应后 再发送下一个数据包 这就是所谓的Nagle算法 在默认情况下 Nagle算法是开启的
这种算法虽然可以有效地改善网络传输的效率 但对于网络速度比较慢 而且对实现性的要求比较高的情况下(如游戏 Telnet等毕运穗) 使用这种方式传输数据会使得客户端有明显的停顿现象 因此 最好的解决方案就是需要Nagle算法时就使用它 不需要时就关闭它 而使用setTcpToDelay正好可以满足这个需求 当使用悄蚂setTcpNoDelay(true)将Nagle算法关闭后 客户端每发送一次数据 无论数据包的大小都会将这些数据发送出去
SO_REUSEADDR
publicbooleangetReuseAddress()(booleanon)throwsSocketException
通过这个选项 可以使多个Socket对象绑定在同一个端口上 其实这样做并没有多大意义 但当使用close方法关闭Socket连接后 Socket对象所绑定的端口并不一定马上释放 系统有时在Socket连接关闭才会再确认一下是否有因为延迟面未到达的数据包 这完全是在底层处理的 也就是说对用户是透明的 因此 在使用Socket类时完全不会感觉到
这种处理机制对于随机绑定端口的Socket对象没有什么影响 但对于绑定在固定端口的Socket对象就可能会抛出 Address already in use JVM_Bind 例外 因此 使用这个选项可以避免个例外的发生
package mynet;import *;importjava io *;publicclass Test{publicstaticvoidmain(String[]args){Socketsocket =newSocket();Socketsocket =newSocket();try手卜{socket setReuseAddress(true);socket bind(newInetSocketAddress( ));System out println( socket getReuseAddress(): +socket getReuseAddress());socket bind(newInetSocketAddress( ));}catch(Exceptione){System out println( error: +e getMessage());try{socket setReuseAddress(true);socket bind(newInetSocketAddress( ));System out println( socket getReuseAddress(): +socket getReuseAddress());System out println( 端口 第二次绑定成功! );}catch(Exceptione ){System out println(e getMessage());}}}}
上面的代码的运行结果如下
socket getReuseAddress():trueerror:Addressalreadyinuse:JVM_Bindsocket getReuseAddress():true端口 第二次绑定成功!
使用SO_REUSEADDR选项时有两点需要注意
必须在调用bind方法之前使用setReuseAddress方法来打开SO_REUSEADDR选项 因此 要想使用SO_REUSEADDR选项 就不能通过Socket类的构造方法来绑定端口
必须将绑定同一个端口的所有的Socket对象的SO_REUSEADDR选项都打开才能起作用 如在例程 中 socket 和socket 都使用了setReuseAddress方法打开了各自的SO_REUSEADDR选项
SO_LINGER
publicintgetSoLinger()(booleanon intlinger)throwsSocketException
这个Socket选项可以影响close方法的行为 在默认情况下 当调用close方法后 将立即返回 如果这时仍然有未被送出的数据包 那么这些数据包将被丢弃 如果将linger参数设为一个正整数n时(n的值最大是 ) 在调用close方法后 将最多被阻塞n秒 在这n秒内 系统将尽量将未送出的数据包发送出去 如果超过了n秒 如果还有未发送的数据包 这些数据包将全部被丢弃 而close方法会立即返回 如果将linger设为 和关闭SO_LINGER选项的作用是一样的
如果底层的Socket实现不支持SO_LINGER都会抛出SocketException例外 当给linger参数传递负数值时 setSoLinger还会抛出一个IllegalArgumentException例外 可以通过getSoLinger方法得到延迟关闭的时间 如果返回 则表明SO_LINGER是关闭的 例如 下面的代码将延迟关闭的时间设为 分钟
if(socket getSoLinger()== )socket setSoLinger(true );
SO_TIMEOUT
publicintgetSoTimeout()(inttimeout)throwsSocketException
这个Socket选项在前面已经讨论过 可以通过这个选项来设置读取数据超时 当输入流的read方法被阻塞时 如果设置timeout(timeout的单位是毫秒) 那么系统在等待了timeout毫秒后会抛出一个InterruptedIOException例外 在抛出例外后 输入流并未关闭 你可以继续通过read方法读取数据
如果将timeout设为 就意味着read将会无限等待下去 直到服务端程序关闭这个Socket 这也是timeout的默认值 如下面的语句将读取数据超时设为 秒
socket setSoTimeout( * );
当底层的Socket实现不支持SO_TIMEOUT选项时 这两个方法将抛出SocketException例外 不能将timeout设为负数 否则setSoTimeout方法将抛出IllegalArgumentException例外
SO_SNDBUF
publicintgetSendBufferSize()(intsize)throwsSocketException
在默认情况下 输出流的发送缓冲区是 个字节( K) 这个值是Java所建议的输出缓冲区的大小 如果这个默认值不能满足要求 可以用setSendBufferSize方法来重新设置缓冲区的大小 但最好不要将输出缓冲区设得太小 否则会导致传输数据过于频繁 从而降低网络传输的效率
如果底层的Socket实现不支持SO_SENDBUF选项 这两个方法将会抛出SocketException例外 必须将size设为正整数 否则setSendBufferedSize方法将抛出IllegalArgumentException例外
SO_RCVBUF
publicintgetReceiveBufferSize()(intsize)throwsSocketException
在默认情况下 输入流的接收缓冲区是 个字节( K) 这个值是Java所建议的输入缓冲区的大小 如果这个默认值不能满足要求 可以用setReceiveBufferSize方法来重新设置缓冲区的大小 但最好不要将输入缓冲区设得太小 否则会导致传输数据过于频繁 从而降低网络传输的效率
如果底层的Socket实现不支持SO_RCVBUF选项 这两个方法将会抛出SocketException例外 必须将size设为正整数 否则setReceiveBufferSize方法将抛出IllegalArgumentException例外
SO_KEEPALIVE
publicbooleangetKeepAlive()(booleanon)throwsSocketException
如果将这个Socket选项打开 客户端Socket每隔段的时间(大约两个小时)就会利用空闲的连接向服务器发送一个数据包 这个数据包并没有其它的作用 只是为了检测一下服务器是否仍处于活动状态 如果服务器未响应这个数据包 在大约 分钟后 客户端Socket再发送一个数据包 如果在 分钟内 服务器还没响应 那么客户端Socket将关闭 如果将Socket选项关闭 客户端Socket在服务器无效的情况下可能会长时间不会关闭 SO_KEEPALIVE选项在默认情况下是关闭的 可以使用如下的语句将这个SO_KEEPALIVE选项打开
socket setKeepAlive(true);
SO_OOBINLINE
publicbooleangetOOBInline()(booleanon)throwsSocketException
如果这个Socket选项打开 可以通过Socket类的sendUrgentData方法向服务器发送一个单字节的数据 这个单字节数据并不经过输出缓冲区 而是立即发出 虽然在客户端并不是使用OutputStream向服务器发送数据 但在服务端程序中这个单字节的数据是和其它的普通数据混在一起的 因此 在服务端程序中并不知道由客户端发过来的数据是由OutputStream还是由sendUrgentData发过来的 下面是sendUrgentData方法的声明
publicvoidsendUrgentData(intdata)throwsIOException
虽然sendUrgentData的参数data是int类型 但只有这个int类型的低字节被发送 其它的三个字节被忽略 下面的代码演示了如何使用SO_OOBINLINE选项来发送单字节数据
package mynet;import *;importjava io *;class Server{publicstaticvoidmain(String[]args)throwsException{ServerSocketserverSocket=newServerSocket( );System out println( 服务器已经启动 端口号 );while(true){Socketsocket=serverSocket accept();socket setOOBInline(true);InputStreamin=socket getInputStream();InputStreamReaderinReader=newInputStreamReader(in);BufferedReaderbReader=newBufferedReader(inReader);System out println(bReader readLine());System out println(bReader readLine());socket close();}}}publicclass Client{publicstaticvoidmain(String[]args)throwsException{Socketsocket=newSocket( );socket setOOBInline(true);OutputStreamout=socket getOutputStream();OutputStreamWriteroutWriter=newOutputStreamWriter(out);outWriter write( );//向服务器发送字符 C outWriter write( helloworld );socket sendUrgentData( );//向服务器发送字符 A socket sendUrgentData( );//向服务器发送字符 B outWriter flush();socket sendUrgentData( );//向服务器发送汉字 中 socket sendUrgentData( );socket sendUrgentData( );//向服务器发送汉字 国 socket sendUrgentData( );socket close();}}
由于运行上面的代码需要一个服务器类 因此 在加了一个类名为Server的服务器类 关于服务端套接字的使用方法将会在后面的文章中详细讨论 在类Server类中只使用了ServerSocket类的accept方法接收客户端的请求 并从客户端传来的数据中读取两行字符串 并显示在控制台上
测试
由于本例使用了 因Server和Client类必须在同一台机器上运行
运行Server
javamynet Server
运行Client
javamynet Client
在服务端控制台的输出结果
服务器已经启动 端口号 ABChelloworld中国
在ClienT类中使用了sendUrgentData方法向服务器发送了字符 A ( )和 B ( ) 但发送 B 时实际发送的是 由于sendUrgentData只发送整型数的低字节 因此 实际发送的是 十进制整型 的二进制形式如图 所示
图 十进制整型 的二进制形式从图 可以看出 虽然 分布在了两个字节上 但它的低字节仍然是
在Client类中使用flush将缓冲区中的数据发送到服务器 我们可以从输出结果发现一个问题 在Client类中先后向服务器发送了 C hello world r n A B 而在服务端程序的控制台上显示的却是ABChello world 这种现象说明使用sendUrgentData方法发送数据后 系统会立即将这些数据发送出去 而使用write发送数据 必须要使用flush方法才会真正发送数据
在Client类中向服务器发送 中国 字符串 由于 中 是由 和 两个字节组成的 而 国 是由 和 两个字节组成的 因此 可分别发送这四个字节来传送 中国 字符串
lishixin/Article/program/Java/hx/201311/26387
Ⅶ 在javasocket网络编程中,开发基于udp协议的程序使用的套接字有哪些
一、 填空题
___ IP地址____用来标志网络中的一个通信实体的地址。通信实体可以是计算机,路由器等。
统一资源定位符URL是指向互联网“资源”的指针,由4部分组成:协议、存放资源的主机域名、__端口___和资源路径和文件名。
URL 是统一资源定位器的简称,它表示Internet上某一资源的地址。
在Socket编程中,IP地址用来标志一台计算机,但是一台计算机上可能提供多种应用程序,使用 端口 来区分这些应用程序。
在Java Socket网络编程中,开发基于TCP协议的服务器端程序使用的套接字是 ServerSocket 。
在Java Socket网络编程中,开发基于UDP协议的程序使用的套接字是 DatagramSocket 。
二、 选择题
1.以下协议都属于TCP/IP协议栈,其中位于传输层的协议是(AD)。(选择二项)
A TCP
B.HTTP
C.SMTP
D.UDP
2.以下协议中属于TCP/IP协议栈中应用层协议的是(A)。(选择一项)
A HTTP
B.TCP
C.UDP
D.IP
3.以下说法中关于UDP协议的说法正确的是(AD)。(选择二项)
A.发送不管对方是否准备好,接收方收到也不确认
B.面向连接
C.占用系统资源多、效率低
D.非常简单的协议,可以广播发送
4.在基于TCP网络通信模式中,客户与服务器程序的主要任务是(BC)。(选择二项)
A 客户程序在网络上找到一条到达服务器的路由
B.客户程序发送请求,并接收服务器的响应
C.服务器程序接收并处理客户请求,然后向客户发送响应结果
D.如果客户程序和服务器都会保证发送的数据不会在传输途中丢失
5.在Java网络编程中,使用客户端套接字Socket创建对象时,需要指定(A)。慧宏(选择一项)
A 服务器主机名称和端口
B.服务器端口和文件
C.服务器名称和文件
D.服务器地址和文件
6.ServerSocket的监听滑碧尺方法accept( )方法的返回值类型是(A )。(选择一项)
A.Socket
B.Void
C.Object
D.DatagramSocket
7.Java UDP Socket编程主要用到的两个类是(BD)。(选择二项信高)
A UDPSocket
B.DatagramSocket
C.UDPPacket
D.DatagramPacket
8.在使用UDP套接字通信时,常用(D)类把要发送的信息打包。(选择一项)
A String
B.DatagramSocket
C.MulticastSocket
D.DatagramPacket
三、 判断题
1. Socket是传输层供给应用层的编程接口,是应用层与传输层之间的桥梁 。( T )
2. TCP/IP传输控制协议是Internet的主要协议,定义了计算机和外设进行通信的规则。TCP/IP网络参考模型包括七个层次:应用层、会话层、表示层、传输层、网络层、链路层和物理层。( F )
3. TCP协议一种面向连接的、可靠的、基于字节流的通信协议 。HTTP、FTP、TELNET、SMTP 都是基于TCP协议的应用层协议。( T )
4. UDP协议是一种面向无连接的、可靠的、基于字节流的传输层通信协议,该协议占用系统资源多、效率较低。( F )
四、 简答题
1.TCP/IP协议栈中,TCP协议和UDP协议的联系和区别?
2.简述基于TCP的Socket编程的主要步骤。提示:分别说明服务器端和客户端的编程步骤。
3.简述基于UDP的Socket编程的主要步骤。提示:分别说明服务器端和客户端的编程步骤。
五、 编码题
1.使用基于TCP的Java Socket编程,完成如下功能:
1) 要求从客户端录入几个字符,发送到服务器端。
2) 由服务器端将接收到的字符进行输出。
3) 服务器端向客户端发出“您的信息已收到”作为响应。
4) 客户端接收服务器端的响应信息。
提示:
服务器端:PrintWriter out =new PrintWriter(socket.getOutputStream(),true);
客户端:BufferedReader line=new BufferedReader(new InputStreamReader(System.in));
Ⅷ linux(或C语言)和JAVA下的socket编程有什么异同点
不同:
1.首先2者提供的接口不同,这点很容易区分。
2.java跨平台,写好的程序不用做任何修改就可以放到linux或者windows或者苹果等诸多操作系统上运行,C当然可以,但linux本身提供了socket的系统调用,你如果使用的是linux系统调用,那么你的程序只能在linux下运行,这点不难理解。但如果是C的库函数,那还是可以跨平台的
3.利用linux系统调用的速度是要快于JAVA提供的SOCKET接口。
相同性我就不说了,你看完我下面的话,你就能理解他们直接的关系了。
从你提出的问题,我觉的你可能对编程不是很了解。
socket是用来实现进程通信(主要是网络通信)的目的,但这不是语言能够解决的问题,确切的说语言连什么是进程他都不知道。这么说来SOCKET不是JAVA带的功能,那么JAVA是如何来实现这一功能的呢?JAVA是通过调用系统提供的SOCKET来完成的。
在LINUX里面,JAVA中的SCOKET最终就是通过调用系统提供的系统调用来完成,而系统调用的SOCKET则是操作系统和硬件共同完成的。所以他们共同点是,如果你的JAVA程序是在LINUX中运行的,那他们通信的具体过程会完全一样,只不过JAVA会在系统调用前面加上一些它认为必需加的东西或者是它认为能够方便编程人员使用的东西。
Ⅸ java socket网络编程
//==============Server.java=================//
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(12345);
System.out.println("服务器就绪,请启动客户端.");
Socket so = s.accept();
byte[] buff = new byte[1024];
int read = so.getInputStream().read(buff);
String[] abc=new String(buff,0,read).split("\\D+");
int a = Integer.parseInt(abc[0]);
int b = Integer.parseInt(abc[1]);
int c = Integer.parseInt(abc[2]);
if(!cbt(a,b,c))
so.getOutputStream().write("输入的数据无法组成三角形.".getBytes());
else
so.getOutputStream().write(getArea(a,b,c).getBytes());
so.getOutputStream().flush();
so.close();
s.close();
}
private static String getArea(int a, int b, int c) {
float s = (a+b+c)/2f;
return "面积: "+Math.sqrt(s*(s-a)*(s-b)*(s-c));
}
private static boolean cbt(int a, int b, int c) {
return a>0&&b>0&&c>0&&a+b>c&&b+c>a&&a+c>b;
}
}
//=================Client.java======================//
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("输入三角形的三边并用逗号隔开,如: (3,4,5) ");
byte[] buff=new byte[64];
int r = System.in.read(buff);
String ipaddr = "localhost";//根据情况改变,在本机调试就不改了
Socket so = new Socket(ipaddr,12345);
so.getOutputStream().write(new String(buff,0,r).getBytes());
r = so.getInputStream().read(buff);
so.close();
String rs = new String(buff,0,r);
System.out.println(rs);
}
}
//先启动Server,再启动Client
Ⅹ C socket编程客户端给JAVA服务器端发送数据问题
不知道你是如何发送数据的?以结构体的形式?还是以字符串的形式?
如果以字符串的形式,应该不存在你说的问题。如果以结构体的形式,JAVA
下是没有结构体的,你是如何接收数据的?
我也写过类似程序,没遇见你说的问题。