통신 프로토콜 및 단순 채팅방 구축
7341 단어 채팅방
1. 시스템의 가장 간단한 클라이언트와 채팅할 수 있는 간단한 서버를 실현
java.net.ServerSocket ss=new java.net.ServerSocket(8888);
java.net.Socket s=ss.accept();
//
java.io.DataOutputStream ds=new java.io.DataOutputStream(s.getOutputStream());
//
java.io.DataInputStream di=new java.io.DataInputStream(s.getInputStream());
String sss=" 、、、、";
ds.write(sss.getBytes());
int t=di.read();
while(t!=13){
System.out.println(t);
t=di.read();
}
s.close();
단지 간단하게 하나의 입력 흐름과 하나의 출력 흐름을 포함하고 출력 흐름에서 자신이 전하는 내용으로 구성된byte 수조를 전달한다.읽으면 한 번에 한 바이트를 읽고 리턴 키를 위해 멈추세요.
2. 이 서버를 가시화하고 서버 만들기 단추를 추가했습니다. 이 단추를 눌렀을 때 입력 상자에 입력한 포트 번호 값을 받아서 ServerSocket 대상을 만들고 여기에 입력 흐름의 라인을 시작합니다. 이것은 서버를 만드는 동시에 클라이언트가 보낸 값을 수신하고 이 값을 setText를 인터페이스에 연결할 수 있음을 의미합니다.보내기 버튼은 먼저 인터페이스에 사용자가 입력한 값을 얻은 후에 그것을 쓰는 것이다.마지막 닫기 단추는 모든 라인의 입력과 출력 흐름을 끄는 것이다.
if(" ".equals(e.getActionCommand())){
String sl=tt.jt2.getText();
if(sl.length()==0){
javax.swing.JOptionPane.showMessageDialog(tt, " ");
System.exit(0);
}
int s2=Integer.parseInt(sl);
try {
//
java.net.ServerSocket ss=new java.net.ServerSocket(s2);
s=ss.accept();
String sss=" 、、、、";
writeMsg(s,sss);
//
readThread tc=new readThread(s,tt);
tc.start();
} catch (Exception ef) {
ef.printStackTrace();
}
}
//
else if(" ".equals(e.getActionCommand())){
String s3=tt.ja2.getText();
s3+="\r
";
writeMsg(s,s3);
tt.ja2.setText("");//
}
//
else if(" ".equals(e.getActionCommand())){
try {
s.close();
System.exit(0);
} catch (Exception e1) {
e1.printStackTrace();
System.exit(0);
}
}
3. 지난번 버전에 버그가 하나 있는데 창설 버튼을 눌렀을 때 클라이언트가 이 Socket 대상을 수신하기를 기다리고 수신하지 않으면 거기에 끼어 죽는다. 그리고 우리는 수신 Socket을 이 라인에 놓고 시작하면 이 문제를 개선할 수 있다.
public void run(){
while(true){
try {
Socket client=server.accept();
readThread rt=new readThread(client,tt);
rt.start();
lis.alist.add(rt);
sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
그리고 이 라인에서 입력 라인을 시작합니다.
4. 다음에 만나는 것은 매번 한 클라이언트와 채팅만 할 수 있고 여러 개의 클라이언트 연결을 실현하려면 같은 서버에 있어야 한다.입력 루트를 시작할 때 서버가 수신하는 모든 Socket 대상은 서로 다른 클라이언트입니다.
public void run(){
while(true){
try {
Socket client=server.accept();
readThread rt=new readThread(client,tt);
rt.start();
lis.alist.add(rt);
sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
5. 클라이언트를 쓰는 것은 서버와 차이가 많지 않다. 인터페이스는 기본적으로 같다. 또한 로그인할 때 IP 주소와 포트를 얻은 후에 실례화된 socket 대상을 만들고 입력 루트를 시작한 다음에 여기서 사용자의 이름을 쓴 다음에 서버에서 읽기 루트를 바꾸고 밖에서 한 번 순환한다. 즉, 대응하는 사용자 이름이다.그리고 닫기 단추를 눌렀을 때 문제가 발생했습니다. 즉, 닫기 단추를 눌렀을 때 입력 흐름이 닫혔지만 라인이 실행 중입니다. 라인의 socket 대상이 비어 있습니다. 이것은 입력 흐름에 판단을 해서 socket 대상이 비어 있는지 판단하도록 요구합니다.
public void run() {
try {
ins = s.getInputStream();
BufferedReader buffReader = new BufferedReader(new InputStreamReader(ins));
while (true) {
if (!s.isClosed()) {
String st = buffReader.readLine();
if (st == null)
return;
String sy = tt.ja1.getText();
st = sy + st + "\r
";// ,
tt.ja1.setText(st);//
} else
return;
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
6. 사실 중간에 많은 버전을 고친 적이 있다. 왜냐하면 내가 사용하는 것은 모두 구조기 전참이기 때문이다. 이렇게 하면 프로그램의 결합성이 비교적 좋지 않기 때문에 한 곳을 바꾸면 큰 문제가 생길 수 있다. 여러 곳을 고쳐야만 이 기능을 실현할 수 있다.나는 이곳이 인터페이스를 사용해야 한다는 것을 알고 있으며, 가장 좋은 방법은 한 종류에 봉인하는 것이지만, 확실히 그럴 리가 없기 때문에 현재 해내지 못했다.
마지막 버전에서는 프로토콜을 사용했습니다. 1은 문자를 보내고 2는 그림 등 파일을 보냅니다.프로토콜 내용은 처음에 전체 파일 길이를 썼고, 다음은 표시자 cmd1 또는 2, 1은 문자를 표시하고, 2는 그림을 표시한다.여기서 판단하면 서로 다른 쓰기 방법에 들어갑니다. 문자를 쓸 때 읽기를 요구할 때 Buffered Read Line을 사용합니다. 이 방법은 뒤에 있는 줄 바꿈표에 따라 한 문장인지 아닌지를 판단합니다. 그러면 한 문장을 보낼 때 뒤에/r/n을 추가하여 읽을 때 한 문장씩 읽을 수 있습니다.
파일을 읽을 때, 먼저 파일 선택 상자를 꺼내서 파일 이름을 선택한 다음, 파일로 흐르는 File InputStreamfis를 읽고, 이것을 파일 길이의byte 그룹에 읽습니다.이것은 표지부를 다 쓴 후에 파일 이름의 길이, 파일 이름, 메시지 내용을 써야 한다.이것이 바로 간단한 완전한 협의이다.
//
else if (" ".equals(e.getActionCommand())) {
if (tt.ja2.getText() != null) {
String s13 = " :" + tt.ja2.getText() + "\r
";
String sy = tt.ja1.getText();
String s14 = sy + s13;
tt.ja1.setText(s14);
try {
for (int i = 0; i < alist.size(); i++) {
System.out.println("--dd"+alist.size());
alist.get(i).dos.writeInt(4+4+s13.length());
alist.get(i).dos.writeInt(1);
alist.get(i).sendMsg(s13);
}
} catch (Exception e1) {
e1.printStackTrace();
}
tt.ja2.setText("");//
} else {
System.out.println(" ");
}
}else
// , int , 2 , , ,
if(" ".equals(e.getActionCommand())){
JFileChooser jfs=new JFileChooser();
jfs.setFileSelectionMode(JFileChooser.FILES_ONLY);
jfs.showOpenDialog(null);
File file=jfs.getSelectedFile();
String fileName=file.getAbsolutePath();
java.io.FileInputStream fis;
byte[] fileByte=null;
try {
fis=new java.io.FileInputStream(fileName);
int fileLen=(int)file.length();
totallenth=4+4+4+fileName.getBytes().length+fileLen;
fileByte=new byte[fileLen];
fis.read(fileByte);
} catch (Exception e1) {
e1.printStackTrace();
}
try {
for (int i = 0; i < alist.size(); i++) {
alist.get(i).dos.writeInt(totallenth);
alist.get(i).dos.writeInt(2);
alist.get(i).dos.writeInt(fileName.getBytes().length);
alist.get(i).sendMsg(fileName);
alist.get(i).dos.write(fileByte);
}
}catch(Exception ef){
ef.printStackTrace();
}
try {
Document doc = tt.ja1.getDocument();
ByteArrayInputStream bis = new ByteArrayInputStream(fileByte);
BufferedImage image = ImageIO.read(bis);
ImageIcon icon = new ImageIcon(image);
tt.ja1.setCaretPosition(doc.getLength());
tt.ja1.insertIcon(icon);
} catch (Exception ed) {
ed.printStackTrace();
}
}
그리고 클라이언트와 서버의 읽기 읽기와 출력 흐름은 모두 엄격하게 협의에 따라 가야 하며, 어느 곳이 안 되면 모두 오류가 발생할 수 있다.
통신은 사실 코드가 어렵지 않지만 통일된 협의를 하려면 업로드를 하는 것이 비교적 번거롭고 약간의 착오가 있어도 안 된다.
이럴 때 코드의 규범성의 중요성을 더욱 느끼게 되고 인터페이스와 방법의 봉인성을 사용할 수 있다면 훨씬 좋아질 것이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
통신 프로토콜 및 단순 채팅방 구축통신의 가장 기본적인 것은 입력 흐름과 출력 흐름, Input Stream과 Output Stream이다.이렇게 처음에 우리는 가장 기본적인 서버를 썼고 이어서 한 걸음 한 걸음 기능을 실현했다. 이 단추를 눌렀을 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.