Javaは、ファイルをアップロードできるサーバーとクライアントを書き込みます。特定のコンテンツは次のとおりです
サーバー側
class server {public static void main(string [] args)スロー例外{//サーバーソケットServersocket ss = new Serversocket(10005); //クライアントソケットFileLoAderSocket = ss.Accept()を受信します。 //接続情報文字列IP = fileLoAderSocket.getInetAddress()。gethostAddress(); system.out.println(ip + "... conncected"); //ファイルを受信し、inputstream in = fileloadersocket.getInputStream()を保存します。 //オブジェクトFilesaveをインスタンス化しますoutputStream filesave = new fileoutputStream( "e://3.mp3"); //配列を作成しますbuf byte [] buf = new byte [1024]; int len = 0; //ファイルの終了が読み取られているかどうかを防御します((len = in.read(buf))!= -1){filesave.write(buf、0、len); // filesave.flush();を更新します。 } //ファイルを返す情報情報bufferedwriter out = new bufferedWriter(new outputStreamWriter(fileloadersocket.getOutputStream())); out.write( "ファイルアップロード成功"); // refresh out.flush(); //リソースを閉じるss.close(); fileloadersocket.close(); filesave.close(); }}クライアント:
class client {public static void main(string [] args)throws exception {//ソケットサービスソケットFileloAdersocket = new Socket( "168.168.168.94"、10005); //クライアントからファイルをローカルに読み取り、ソケットの出力ストリームに書き込みますoutputStream out = fileloadersocket.getOutputStream(); //オブジェクトをインスタンス化しますfileReader inputstream fileread = new fileinputStream( "g://2.mp3"); //配列バイトを作成します[] buf = new byte [1024]; int len = 0; //ファイルの最後が読み取られているかどうかを判断します((len = fileread.read(buf))!= -1){out.write(buf、0、len); } //ファイルがfileloadersocket.shutdownoutput()に転送されたことをサーバーに伝えます。 // Server BufferedReader in = new BufferedReader(new inputstreamReader(fileloadersocket.getInputStream()))から情報フィードバックを取得します。 string serverback = in.readline(); system.out.println(serverback); //リソースclose fileloadersocket.close(); fileread.close(); }}次のプログラムは、参照を学習するために他の場所から直接コピーされます。
Javaソケットプログラミング
Javaソケットプログラミングには、2つの概念があります。1つはServersocket、もう1つはソケットです。サーバーとクライアントはソケットを介して接続されており、通信できます。まず、Serversocketはサーバー上のポートを聴きます。クライアントに接続を試みるソケットがあることがわかった場合、ソケットの接続要求を受け入れ、同時にサーバーに対応するソケットを確立して通信します。このようにして、2つのソケットがあります。1つはクライアントに、もう1つはサーバーに1つあります。
ソケット間の通信は実際には非常に簡単です。サーバーがソケット出力ストリームに何かを書き込むと、クライアントはソケット入力ストリームを介して対応するコンテンツを読み取ることができます。ソケットとソケットは2つの方向に接続されているため、クライアントは対応するソケット出力ストリームに物事を書き込むこともでき、サーバーの対応するソケット入力ストリームは対応するコンテンツを読み取ることができます。クライアントとのサーバー側の通信の例を次に示します。
1。クライアントの書き込みとサーバーの読み取り
サーバーJavaコード
public class server {public static void main(string args [])throws ioexception {//簡単にするために、すべての例外情報がint port = 8899; //ポート8899 Serversocket Server = new Serversocket(ポート)でサーバーソケットリスニングを定義します。 //サーバーは、他のソケットから接続要求を受信しようとします。サーバーの受け入れメソッドは、ブロッキングソケットソケット= server.accept()です。 //クライアントとの接続を確立した後、ソケットの入力ストリームを取得し、クライアントから送信された情報を読むことができます。 reader reader = new inputStreamReader(socket.getInputStream()); char chars [] = new char [64]; int len; stringbuilder sb = new StringBuilder(); while((len = reader.read(chars))!= -1){sb.append(new String(chars、0、len)); } system.out.println( "from client:" + sb); reader.close(); socket.close(); server.close(); }}ソケットの入力ストリームからデータを読み取るためのサーバーの操作もブロックしています。データが入力ストリームから読み取られていない場合、クライアントがソケットの出力ストリームにデータを書き込むか、ソケットの出力ストリームを閉じるまで、プログラムはそこに残ります。もちろん、クライアントソケットにも同じことが言えます。操作が完了したら、プログラム全体が完了する前に、対応するリソースを閉じることを忘れないでください。つまり、対応するIOストリームとソケットを閉じます。
クライアントJavaコード
public class client {public static void main(string args [])throws exception {//簡単にするために、すべての例外が直接string host = "127.0.0.1"; //接続するサーバーのIPアドレスは、int port = 8899です。 //接続するサーバーの対応するリスニングポート//接続は、サーバーソケットクライアント= new Socket(host、port)で確立されます。 //接続を確立した後、サーバーライターにデータを書き込むことができます= new outputStreamWriter(client.getOutputStream()); writer.write( "hello server。"); writer.flush(); // flush writer.close(); client.close(); }}ソケット出力ストリームにデータを書き込むときは、1つのことに注意を払う必要があります。プログラムが書き込み操作後の出力ストリームのシャットダウンに対応していないが、他のブロッキング操作(入力ストリームの読み取りなど)を実行する場合は、フラッシュすることを忘れないでください。この方法でのみ、サーバーはクライアントから送信されたデータを受信できます。そうしないと、お互いを待機していない場合があります。この問題は、クライアントとサーバーの読み取りと書き込みについて同時に話すときに後で言及します。
2。クライアントとサーバーが同時に読み書き
前述のように、ソケットは双方向の方法で通信し、データを受信してデータを送信できます。
サーバーJavaコード
public class server {public static void main(string args [])throws ioexception {//簡単にするために、すべての例外情報がint port = 8899; //ポート8899 Serversocket Server = new Serversocket(ポート)でサーバーソケットリスニングを定義します。 //サーバーは、他のソケットから接続要求を受信しようとします。サーバーの受け入れメソッドは、ブロッキングソケットソケット= server.accept()です。 //クライアントとの接続を確立した後、ソケットの入力ストリームを取得し、クライアントから送信された情報を読むことができます。 reader reader = new inputStreamReader(socket.getInputStream()); char chars [] = new char [64]; int len; stringbuilder sb = new StringBuilder(); while((len = reader.read(chars))!= -1){sb.append(new String(chars、0、len)); } system.out.println( "from client:" + sb); //それを読んだ後に文を書くライターwriter = new outputStreamWriter(socket.getOutputStream()); writer.write( "hello client。"); writer.flush(); writer.close(); reader.close(); socket.close(); server.close(); }}上記のコードでは、最初に入力ストリームからクライアントが送信したデータを読み取り、次にデータをクライアントに出力ストリームに書き込み、対応するリソースファイルを閉じます。実際、入力ストリームからデータを読むことはブロッキング操作であるため、上記のコードは事前に想定された方法で実行されない場合があります。ループ中に上記のデータが読み取られると、ループ本体が実行されます。そうしないと、ブロックされ、後続の書き込み操作は実行されません。クライアントの対応するソケットが閉じてブロックされていない限り、whileループは停止します。これが実行されないこの状況の解決策は、whileループを条件付きで飛び出す必要があることです。上記のコードを見ると、変更される唯一のものは、LENの長さと読み取りデータです。レンはもはや使用できません。使用できるのは、読み取られるデータだけです。この場合、通常、エンドタグに同意します。クライアントから送信されたデータに特定のエンドタグが含まれている場合、現在のデータが送信されたことを意味し、この時点でループアウトできます。その後、改善されたコードは次のようになります。
Javaコード
public class server {public static void main(string args [])throws ioexception {//簡単にするために、すべての例外情報がint port = 8899; //ポート8899 Serversocket Server = new Serversocket(ポート)でサーバーソケットリスニングを定義します。 //サーバーは、他のソケットから接続要求を受信しようとします。サーバーの受け入れメソッドは、ブロッキングソケットソケット= server.accept()です。 //クライアントとの接続を確立した後、ソケットの入力ストリームを取得し、クライアントから送信された情報を読むことができます。 reader reader = new inputStreamReader(socket.getInputStream()); char chars [] = new char [64]; int len; stringbuilder sb = new StringBuilder();弦の温度; intインデックス; while((len = reader.read(chars))!= -1){temp = new String(chars、0、len); if((index = temp.indexof( "eof"))!= -1){// eofがsb.append(temp.substring(0、index))が発生したときに受信が終了します。壊す; } sb.append(temp); } system.out.println( "from client:" + sb); //ライターライター= new outputStreamWriter(socket.getOutputStream())の後に文を書く; writer.write( "hello client。"); writer.flush(); writer.close(); reader.close(); socket.close(); server.close(); }}上記のコードでは、サーバーがクライアントによって送信されたエンドマーク、つまり「EOF」が終了すると、データ受信が終了し、ループが終了し、後続のコードが続くことができます。
クライアントJavaコード
public class client {public static void main(string args [])throws exception {//簡単にするために、すべての例外が直接string host = "127.0.0.1"; //接続されるサーバーのIPアドレスint port = 8899; //接続するサーバーの対応するリスニングポート//接続は、サーバーソケットクライアント= new Socket(host、port)で確立されます。 //接続を確立した後、サーバーライターにデータを書き込むことができます= new outputStreamWriter(client.getOutputStream()); writer.write( "hello server。"); writer.flush(); // reader reader = new inputStreamReader(client.getInputStream())を書いた後に読むchar chars [] = new char [64]; int len; stringbuffer sb = new StringBuffer(); while((len = reader.read(chars))!= -1){sb.append(new String(chars、0、len)); } system.out.println( "from server:" + sb); writer.close(); reader.close(); client.close(); }}上記のコードでは、最初にサーバーにデータを送信し、次にサーバーによって返されたデータを読み取ります。以前のサーバーと同様に、プログラムが常にそこに垂れ下がっている可能性があり、その間のループから飛び出すことはありません。このコードはサーバーの最初のコードと組み合わされているので、サーバーが常にそこにデータを受信し、whileループから飛び出すことはないことを分析してみましょう。ソリューションは、サーバーの2番目のコードに示されています。クライアントがデータを送信した後、エンドマークを出力ストリームに書き込み、データが送信されたことをサーバーに伝えます。サーバーは、データが返された後にクライアントに伝えるためのマークを送信します。その後、変更されたクライアントコードは次のようになります。
Javaコード
public class client {public static void main(string args [])throws exception {//簡単にするために、すべての例外が直接string host = "127.0.0.1"; //接続するサーバーのIPアドレスは、int port = 8899です。 //接続するサーバーの対応するリスニングポート//接続は、サーバーソケットクライアント= new Socket(host、port)で確立されます。 //接続を確立した後、サーバーライターにデータを書き込むことができます= new outputStreamWriter(client.getOutputStream()); writer.write( "hello server。"); writer.write( "eof"); writer.flush(); // reader reader = new inputStreamReader(client.getInputStream())を書いた後に読むchar chars [] = new char [64]; int len; stringbuffer sb = new StringBuffer();弦の温度; intインデックス; while((len = reader.read(chars))!= -1){temp = new String(chars、0、len); if((index = temp.indexof( "eof"))!= -1){sb.append(temp.substring(0、index));壊す; } sb.append(new String(chars、0、len)); } system.out.println( "from server:" + sb); writer.close(); reader.close(); client.close(); }}私たちが日常生活で使用する最も一般的なフォームは、クライアントがサーバーにデータを送信し、サーバーがデータを受信し、対応する結果をクライアントに返すことです。ただし、クライアントとサーバーの間には1対1の関係はありませんが、複数のクライアントが以下に言及したのと同じサーバーに対応する状況はもはやありません。
3.複数のクライアントが同じサーバーに接続します
上記の2つの例では、サーバーはクライアントのリクエストを受信した後に終了し、他のクライアントからリクエストを受信できません。通常、これを行います:
Javaコード
public class server {public static void main(string args [])throws ioexception {//簡単にするために、すべての例外情報がint port = 8899; //ポート8899 Serversocket Server = new Serversocket(ポート)でサーバーソケットリスニングを定義します。 while(true){//サーバーは他のソケットから接続要求を受信しようとします。サーバーの受け入れメソッドは、ブロッキングソケットソケット= server.accept()です。 //クライアントとの接続を確立した後、ソケットの入力ストリームを取得し、クライアントから送信された情報を読むことができます。 reader reader = new inputStreamReader(socket.getInputStream()); char chars [] = new char [64]; int len; stringbuilder sb = new StringBuilder();弦の温度; intインデックス; while((len = reader.read(chars))!= -1){temp = new String(chars、0、len); if((index = temp.indexof( "eof"))!= -1){// eofがsb.append(temp.substring(0、index))が発生したときに受信が終了します。壊す; } sb.append(temp); } system.out.println( "from client:" + sb); //ライターライター= new outputStreamWriter(socket.getOutputStream())の後に文を書く; writer.write( "hello client。"); writer.flush(); writer.close(); reader.close(); socket.close(); }}}上記のコードでは、デッドループを使用しました。そこでは、Serversocketがクライアントから接続リクエストを受信しようとすることを受け入れる方法を呼び出します。リクエストが受信されない場合、プログラムはクライアントから接続リクエストを受信し、接続を確立したクライアントと通信するまでここでブロックされます。その後、ループ本体を実行し、新しい接続要求を再度受信しようとします。これにより、Serversocketはすべてのクライアントから接続リクエストを受信し、それらと通信できます。これにより、1つのサーバー上の複数のクライアントとの簡単な通信モードが実装されます。
上記の例では、複数のクライアントと通信するために1つのサーバーが実装されていますが、まだ問題があります。上記の例では、サーバーはクライアントの接続要求を同期して処理します。クライアントから接続要求を受信するたびに、次の接続リクエストを処理する前に、まず現在のクライアントと通信する必要があります。これは、より並行性がある場合、プログラムのパフォーマンスに深刻な影響を与えます。このため、クライアントとの通信の非同期処理に変更できます。
Javaコード
public class server {public static void main(string args [])throws ioexception {//簡単にするために、すべての例外情報がint port = 8899; //ポート8899 Serversocket Server = new Serversocket(ポート)でサーバーソケットリスニングを定義します。 while(true){//サーバーは他のソケットから接続要求を受信しようとします。サーバーの受け入れメソッドは、ブロッキングソケットソケット= server.accept()です。 //ソケットが受信されるたびに、新しいスレッド(新しいタスク(ソケット))を処理するために新しいスレッドが確立されます。start(); }} / ** * * / staticクラスタスクはrunnable {private socket socket;パブリックタスク(ソケットソケット){this.socket = socket; } public void run(){try {handleSocket(); } catch(Exception e){e.printstacktrace(); }} / ***クライアントソケットと通信* @throws例外* / private void handlesocket()throws exception {reader reader = new inputStreamReader(socket.getInputStream()); char chars [] = new char [64]; int len; stringbuilder sb = new StringBuilder();弦の温度; intインデックス; while((len = reader.read(chars))!= -1){temp = new String(chars、0、len); if((index = temp.indexof( "eof"))!= -1){// eofがsb.append(temp.substring(0、index))が発生したときに受信が終了します。壊す; } sb.append(temp); } system.out.println( "from client:" + sb); //ライターライター= new outputStreamWriter(socket.getOutputStream())の後に文を書く; writer.write( "hello client。"); writer.flush(); writer.close(); reader.close(); socket.close(); }}}上記のコードでは、Serversocketが新しいソケット接続要求を受信するたびに、新しいスレッドが生成され、現在のソケットと通信され、クライアントソケットとの通信の非同期処理が実現されます。
Socketの入力ストリームからデータを受信するとき、上記のように少し読むことは複雑すぎます。時々、BufferedReaderを使用して、次のように一度に1行ずつ読み取ります。
Javaコード
public class server {public static void main(string args [])throws ioexception {//簡単にするために、すべての例外情報がint port = 8899; //ポート8899 Serversocket Server = new Serversocket(ポート)でサーバーソケットリスニングを定義します。 while(true){//サーバーは他のソケットから接続要求を受信しようとします。サーバーの受け入れメソッドは、ブロッキングソケットソケット= server.accept()です。 //ソケットが受信されるたびに、新しいスレッド(新しいタスク(ソケット))を処理するために新しいスレッドが確立されます。start(); }} / ** * * / staticクラスタスクはrunnable {private socket socket;パブリックタスク(ソケットソケット){this.socket = socket; } public void run(){try {handleSocket(); } catch(Exception e){e.printstacktrace(); }} / ***クライアントソケットと通信* @Throws例外* / private void handleSocket()スロー例外{bufferedReader br = new bufferedReader(new inputStreamReader(socket.getInputStream())); stringbuilder sb = new StringBuilder();弦の温度; intインデックス; while((temp = br.readline())!= null){system.out.println(temp); if((index = temp.indexof( "eof"))!= -1){// eofに遭遇したときに受信を終了します。壊す; } sb.append(temp); } system.out.println( "from client:" + sb); //ライターライター= new outputStreamWriter(socket.getOutputStream())の後に文を書く; writer.write( "hello client。"); writer.write( "eof/n"); writer.flush(); writer.close(); br.close(); socket.close(); }}}現時点では、BufferedReaderのReadLineメソッドが一度に1行ずつ読み取ることに注意する必要があります。この方法はブロックされています。プログラムは、1行のデータを読み取るまで実行され続けません。では、readlineはいつ行を読みますか? ReadLineメソッドは、プログラムが対応するストリームの新しいラインまたはエンディング文字に遭遇するまで、それが行を読み取られたとは考えません。閉塞を終了し、プログラムを実行し続けます。したがって、BufferedReaderのReadlineを使用してデータを読み取る場合、対応する出力ストリームにラインブレークを書き込むことを忘れないでください(ストリームが終了した後、自動的にエンドとしてマークされ、ReadLineを認識できます)。ラインが破損した後、出力ストリームがすぐに閉じられない場合はフラッシュすることを忘れないでください。そうすれば、データはバッファーから本当に書き込まれます。上記のコードに対応すると、クライアントプログラムは次のように記述する必要があります。
Javaコード
public class client {public static void main(string args [])throws exception {//簡単にするために、すべての例外が直接string host = "127.0.0.1"; //接続するサーバーのIPアドレスは、int port = 8899です。 //接続するサーバーの対応するリスニングポート//接続は、サーバーソケットクライアント= new Socket(host、port)で確立されます。 //接続を確立した後、サーバーライターにデータを書き込むことができます= new outputStreamWriter(client.getOutputStream()); writer.write( "hello server。"); writer.write( "eof/n"); writer.flush(); // bufferedReader br = new BufferedReader(new inputStreamReader(client.getInputStream()))を作成した後に読み取ります。 stringbuffer sb = new StringBuffer();弦の温度; intインデックス; while((temp = br.readline())!= null){if((index = temp.indexof( "eof"))!= -1){sb.substring(0、index));壊す; } sb.append(temp); } system.out.println( "from server:" + sb); writer.close(); br.close(); client.close(); }}4.タイムアウト時間を設定します
クライアントがソケットを介してサーバーからXX情報を取得し、ページ上のユーザーに表示する必要があるような要件があるとします。データを読み取るときにソケットがブロックしていることを知っています。データを読んでいない場合、プログラムはそこでブロックし続けます。リクエストを同期するときは、そのような状況が起こってはなりません。これには、プログラムが実行され続けることができるように、リクエストが特定の時間に達した後、ブロッキング割り込みを制御する必要があります。 Socketは、Millisecondsで受信したデータのタイムアウト時間を設定するSetSoTimeout()メソッドを提供します。設定されたタイムアウト時間が0より大きく、この時間の後、ソケットが返されたデータを受信していない場合、ソケットはSockettimeOutExceptionを投げます。
データを読み始めてから10秒間データを読み取る前に、クライアントを中断してブロックするようにクライアントを制御する必要があるとします。これを行うことができます。
Javaコード
public class client {public static void main(string args [])throws exception {//簡単にするために、すべての例外が直接string host = "127.0.0.1"; //接続するサーバーのIPアドレスは、int port = 8899です。 //接続するサーバーの対応するリスニングポート//接続は、サーバーソケットクライアント= new Socket(host、port)で確立されます。 //接続を確立した後、サーバーライターにデータを書き込むことができます= new outputStreamWriter(client.getOutputStream()); writer.write( "hello server。"); writer.write( "eof/n"); writer.flush(); // bufferedReader br = new BufferedReader(new inputStreamReader(client.getInputStream()))を作成した後に読み取ります。 //タイムアウトを10秒client.setsotimeout(10*1000)に設定します。 stringbuffer sb = new StringBuffer();弦の温度; intインデックス; try {while((temp = br.readline())!= null){if((index = temp.indexof( "eof"))!= -1){sb.append(temp.substring(0、index));壊す; } sb.append(temp); }} catch(sockettimeoutexception e){system.out.println( "data read timeout。"); } system.out.println( "from server:" + sb); writer.close(); br.close(); client.close(); }}5.データのガラブルコードを受信します
サーバーまたはクライアントが文字化けされた中国のコードを受信する場合、それは通常、データが送信されたときに使用されるエンコードがデータの受信時に使用されるエンコードと矛盾するためです。たとえば、次のようなサーバーコードがあります。
Javaコード
public class server {public static void main(string args [])throws ioexception {//簡単にするために、すべての例外情報がint port = 8899; //ポート8899 Serversocket Server = new Serversocket(ポート)でサーバーソケットリスニングを定義します。 while(true){//サーバーは他のソケットから接続要求を受信しようとします。サーバーの受け入れメソッドは、ブロッキングソケットソケット= server.accept()です。 //ソケットが受信されるたびに、新しいスレッド(新しいタスク(ソケット))を処理するために新しいスレッドが確立されます。start(); }} / ** * * / staticクラスタスクはrunnable {private socket socket;パブリックタスク(ソケットソケット){this.socket = socket; } public void run(){try {handleSocket(); } catch(Exception e){e.printstacktrace(); }} / ***クライアントソケットと通信* @Throws例外* / private void handlesocket()throws exception {bufferedreader br = new bufferedReader(new inputstreamReader(socket.getinputStream()、 "gbk")); stringbuilder sb = new StringBuilder();弦の温度; intインデックス; while((temp = br.readline())!= null){system.out.println(temp); if((index = temp.indexof( "eof"))!= -1){// EOFが遭遇したときの受信を終了しました。壊す; } sb.append(temp); } system.out.println( "client:" + sb); //ライターライター= new outputStreamWriter(socket.getOutputStream()、 "utf-8"); writer.write( "hello、client。"); writer.write( "eof/n"); writer.flush(); writer.close(); br.close(); socket.close(); }}}ここでテストに使用したとき、私は少し混乱しています。上記のサーバーコードでは、入力ストリームを定義するときにデータを読み取るためにGBKエンコードの使用を明確に定義し、出力ストリームを定義するときにデータを送信するためにUTF-8エンコードの使用を明確に指定します。クライアントがクライアントにデータを送信するときにGBKエンコーディングのデータを送信しない場合、サーバーが受信したデータはガーブルされている可能性があります。同様に、サーバー上のデータを送信するときにクライアントがエンコードを送信しない場合、つまりデータを受信するためにUTF-8エンコードが発生する場合、データが発生する可能性も非常に高いです。したがって、上記のサーバーコードの場合、プログラムがCarled Codeなしで相手が送信したデータを読み取るために、クライアントは次のようにする必要があります。
Javaコード
public class client {public static void main(string args [])throws exception {//簡単にするために、すべての例外が直接string host = "127.0.0.1"; //接続されるサーバーのIPアドレスint port = 8899; //接続するサーバーの対応するリスニングポート//接続は、サーバーソケットクライアント= new Socket(host、port)で確立されます。 //接続を確立した後、サーバーライターにデータを書き込むことができます= new outputStreamWriter(client.getOutputStream()、 "gbk"); writer.write( "hello、server。"); writer.write( "eof/n"); writer.flush(); // bufferedreader br = new BufferedReader(new inputstreamReader(client.getInputStream()、 "utf-8"))を作成した後に読み取ります。 //タイムアウトを10秒client.setsotimeout(10*1000)に設定します。 stringbuffer sb = new StringBuffer();弦の温度; intインデックス; try {while((temp = br.readline())!= null){if((index = temp.indexof( "eof"))!= -1){sb.append(temp.substring(0、index));壊す; } sb.append(temp); }} catch(sockettimeoutexception e){system.out.println( "data read timeout。"); } system.out.println( "server:" + sb); writer.close(); br.close(); client.close(); }}この記事は「Javaアップロード操作技術の要約」にまとめられており、誰もが学習して読むことを歓迎します。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。