자바 socket 통신 흐름 테스트

8768 단어 java socket
장면
클 라 이언 트 서버 연결 만 들 기
클 라 이언 트 가 서버 에 데 이 터 를 보 내 처리 합 니 다.
서버 에서 입력 흐름 에서 데이터, 처리 중.....
이 때 클 라 이언 트 가 연결 을 끊 습 니 다.
서버 에서 처 리 된 데 이 터 를 고객 에 게 보 냅 니 다. 예상 되 는 경우 연결 이 끊 겼 고 출력 흐름 이 존재 하지 않 습 니 다. write 할 때 오 류 를 보고 해 야 합 니 다.
package tcp;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class TcpClient {
	public static void main(String[] args) {
		try {
			Socket s = new Socket("127.0.0.1", 8080);
//			s.setTcpNoDelay(true);
			// InputStream is = s.getInputStream();
			OutputStream os = s.getOutputStream();
			DataOutputStream os_d = new DataOutputStream(os);
			for (;;) {//          
				InputStreamReader input = new InputStreamReader(System.in);
				BufferedReader read = new BufferedReader(input);
				String content = read.readLine();
				if ("exit".equals(content)) {
					s.close();
					return;
				}
				System.out.println("      ," + content);
				os_d.writeBytes(content + System.getProperty("line.separator"));
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 
package tcp;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {

	//          
	public static void main(String[] args) throws IOException {
		ServerSocket serverSocket = new ServerSocket(8080);
		System.out.println("tcp      ....");
		while (1 == 1) {
			Socket socket = serverSocket.accept();//       
			socket.setOOBInline(false);
			System.out.println("      " + socket);
			// socket.setSoTimeout(10*1000);//readLine    10s,              java.net.SocketTimeoutException
//			socket
			InputStream inputStream = socket.getInputStream();
			OutputStream outputStream = socket.getOutputStream();
			BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
			System.out.println("       ...");
			while (true) {//        
				System.out.println("      ");
				String readLine = bufferedReader.readLine();
				if (readLine == null) {
					return;
				}
				System.out.println("    :" + readLine);
				try {
					System.out.println("     .....");
					Thread.sleep(10*1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				StringBuffer sb=new StringBuffer();
//				for(int i=0;i<10000;i++)
//					sb.append("aaaaaaaaaaaaaa");
				bufferedWriter.write(readLine+","+sb.toString());
				bufferedWriter.flush();
				System.out.println("     OK");
				try {
					Thread.sleep(10*1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

 
클 라 이언 트 콘 솔
aaa
메시지 보 내기 시작
exit
 
서버 콘 솔
tcp 서버 오픈...
소켓 [addr =/127.0.1, port = 3643, localport = 8080] 연결 을 가 져 왔 습 니 다.
클 라 이언 트 정보 수신...
사용자 입력 대기
메시지 수신: aaa
백 스테이지 처리 중...
응답 클 라 이언 트 OK
사용자 입력 대기
Exception in thread "main"java.net.SocketException: Software caused connection abort: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at tcp.TcpServer.main(TcpServer.java:32)
 
서버 가 write 를 할 때 문제 가 없 었 다 는 것 을 설명 합 니 다. 다음 read 에서 야 연결 이 끊 겨 비슷 한 이상 을 읽 을 수 없습니다.
 
왜 일 까요?
어디 썼 지?나 는 특별히 bufferedWriter. flush ();다 괜찮아.
 
만약 응답 한 것 이 대량의 데이터 라면?아 날로 그 코드 는 다음 과 같 습 니 다.
for(int i=0;i<10000;i++)
 sb.append("aaaaaaaaaaaaaa");
bufferedWriter.write(readLine+","+sb.toString());
 
bufferedWriter.flush();
이때 예 상 했 던 상황 이 왔 다.
tcp 서버 오픈...
소켓 [addr =/127.0.1, port = 3706, localport = 8080] 연결 을 가 져 왔 습 니 다.
클 라 이언 트 정보 수신...
사용자 입력 대기
메시지 수신: aa
백 스테이지 처리 중...
Exception in thread "main"java.net.SocketException: Software caused connection abort: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)
at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:263)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:106)
at java.io.OutputStreamWriter.write(OutputStreamWriter.java:190)
at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:111)
at java.io.BufferedWriter.write(BufferedWriter.java:212)
at java.io.Writer.write(Writer.java:140)
at tcp.TcpServer.main(TcpServer.java:46)
 
 
왜 그 럴 까요?캐 시 문제 로 추정 되 며, 구체 적 인 socket 통신 체제 와 관련 이 있 을 수 있 습 니 다.
Socket setSoLinger 
Enable/disable SO_LINGER with the specified linger time in seconds. The maximum timeout value is platform specific. The setting only affects socket close.
기본 적 인 상황 에서 close 연결 은 실제 시스템 이 한 동안 머 물 러 야 진정 으로 닫 힐 수 있 습 니 다. 코드 close 는 가상 일 뿐 입 니 다.
구체 적 으로 얼마나 머 무 를 지 는 시스템 플랫폼 에서 결정 된다.앞 에 있 는 write 가 진짜 인가 봐 요. OK.
 
코드 를 수정 하여 서버 의 처리 시간 을 연장 하 다.다시 해 봐.
System. out. println ("배경 처리 중...");
Thread.sleep(60*1000);
여기 서 1 분 의 상황 을 처리 하 는 것 은 이전 과 마찬가지 로 나 는 2 변 의 통신 방식 이 다음 과 같다 고 추측한다.
서버 에서 write 가 나 왔 을 때 세 번 의 악 수 를 통 해 누군가가 나 에 게 close 를 요청 했다 고 알려 주 었 다. 더 이상 나 에 게 데 이 터 를 보 내지 말 라 고 했다.
이번 수신 은 데이터 의 완전 성 을 확보 하기 위해 서 입 니 다. 제 가 닫 은 후에 바로 다른 socket 이 저 를 사칭 하여 처리 한 데 이 터 를 '사기꾼' 에 게 보 낼 까 봐 걱정 입 니 다.
상대방 에 게 문제 가 생 겼 다 는 것 을 알 게 되 었 습 니 다.
이것 은 단지 추측 일 뿐, 좀 더 검증 이 필요 하 다.
 
 
재 테스트
클 라 이언 트 에서 코드 수정
Socket s = new Socket("127.0.0.1", 8080);
s.setSoLinger(true, 0);
close 후 머 무 르 지 않 고 시스템 을 직접 닫 습 니 다.
 
 
tcp 서버 오픈...
소켓 [addr =/127.0.1, port = 3842, localport = 8080] 연결 을 가 져 왔 습 니 다.
클 라 이언 트 정보 수신...
사용자 입력 대기
메시지 수신: ff
백 스테이지 처리 중...
Exception in thread "main"java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:276)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:122)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:212)
at java.io.BufferedWriter.flush(BufferedWriter.java:236)
at tcp.TcpServer.main(TcpServer.java:42)
 
이때 가 예 상 된 상황 이다.
 
 
 
여기에 또 하나의 문제 가 있 을 수 있 습 니 다. 바로 제 가 클 라 이언 트 에 게 대량의 데 이 터 를 보 낼 때 도 write 의 이상 을 보고 하 는 이 유 는 무엇 입 니까?
코드:
for(int i=0;i<10000;i++)
 sb.append("aaaaaaaaaaaaaa");
bufferedWriter.write(readLine+","+sb.toString());
 
bufferedWriter.flush();
그 이 유 는 그 렇 겠 지.TCP 밑바닥 의 경우 매번 통신 은 가방 을 발송 하 는데 소포 가 너무 크 면 여러 개의 작은 가방 을 낸다
분할 발송, 첫 발송 시 이미 발송 성공 하 였 으 나, 상대방 은 이미 자신 이 닫 힌 상태 로 발송 하 였 습 니 다
서버 가 생 겼 습 니 다. 이때 서버 에서 다시 가방 을 보 내 면 바로 실 패 했 습 니 다.
TCP_NODELAY
SO_TIMEOUT
SO_LINGER
SO_RCVBUF
SO_SNDBUF
TCP 통신 체 제 를 체계적으로 공부 할 시간 이 있 을 것 같 습 니 다.
 

좋은 웹페이지 즐겨찾기