Ⅰ 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
下是沒有結構體的,你是如何接收數據的?
我也寫過類似程序,沒遇見你說的問題。