通信软件设计实验报告网络编程.docx
《通信软件设计实验报告网络编程.docx》由会员分享,可在线阅读,更多相关《通信软件设计实验报告网络编程.docx(14页珍藏版)》请在冰豆网上搜索。
![通信软件设计实验报告网络编程.docx](https://file1.bdocx.com/fileroot1/2023-1/8/798fc835-1df8-466a-8a2c-a3cae44eb502/798fc835-1df8-466a-8a2c-a3cae44eb5021.gif)
通信软件设计实验报告网络编程
网络编程及模拟购票程序
1、程序思路
1.Socket简介
Socket是网络上运行的两个程序间双向通行的一端,它既可以接受请求,也可以发送请求,利用它可以较为方便地实现网络上的数据的传递。
在JAVA中,专门有Socket类来处理用户的请求和响应。
利用Socket类的方法,就可以实现两台计算机之间的通信。
在JAVA中,可以将Socket理解为客户端或者服务端的一个特殊的对象,这个对象有两个关键的方法,一个是getInputStream()方法,另一个是getOutputStream()方法。
前一个方法用于得到一个输入流,后一个方法用于得到一个输出流。
Socket有两种主要的操作方式:
面向连接的和面向无连接的。
面向连接的socket操作就像一部电话,它们必须建立一个连接和一个呼叫。
所有的事情到达时的顺序与它们出发时的顺序是一样的。
无连接的socket操作就像是一个邮件投递,没有什么保证,多个邮件可能到达时的顺序与出发时的顺序不一样。
2.Java多线程
线程的特征是:
(1)在java中,程序通过流控制来执行程序流。
程序中单个顺序的流控制称为线程。
(2)多线程指的是在单个进程中可以同时运行多个不同的线程,执行不同的任务。
多线程意味着一个程序的多行语句可以看上去几乎同时运行。
多线程的应用范围很广。
一般情况下,程序的某些部分同特定的事件或资源联系在一起,同时又不想为它而暂停程序其它部分的执行,在这种情况下,就可以考虑创建一个线程,令他与那个事件或资源关联到一起,并让它独立于主程序运行。
通过使用线程,可以避免用户在运行程序和得到结果之间的停顿,还可以让一些任务在后台运行,而用户则在前台继续完成一些其他的工作。
总之,利用多线程技术,可以使编程人员方便地开发出能同时完成处理多个任务的功能强大的应用程序。
二、实现关键技术点
1.服务端的编写
为了支持多个客户端同时访问服务端,服务端需要支持多线程来完成并发访问。
在完成模拟购票的过程中,服务端初始的票数为20,在多个客户端进行访问时为避免重复购票或者购票次序混乱,需要同步购票代码块。
为实现客户端与服务端实现通信,需要简单的编写一个简单的通信协议。
以下为服务端的代码:
packageserver2;
importjava.io.IOException;
import.ServerSocket;
import.Socket;
importjava.util.ArrayList;
publicclassServerThread{
publicServerThread()
{
ServerSocketserversocket=null;
try{
serversocket=newServerSocket(1234);
while(true)
{
Socketclientsocket=serversocket.accept();
ThreadServerthreadserver=newThreadServer(clientsocket);
Threadt=newThread(threadserver);
t.start();
}
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
publicstaticvoidmain(String[]args)
{
newServerThread();
}
}
通信协议及事务处理方面的代码如下:
packageserver2;
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
import.Socket;
importjava.util.ArrayList;
importjava.util.Iterator;
importjava.util.List;
classThreadServerimplementsRunnable{
privateSocketcs;
privateBufferedReaderin;
privateBufferedWriterout;
privateArrayListticket=newArrayList();
publicvoidsetTicket()
{
for(inti=0;i<20;i++)
{
ticket.add(i);
}
}
publicvoidsendMessage(Stringmsg)
{
try{
out=newBufferedWriter(newOutputStreamWriter(cs.getOutputStream()));
out.write(msg);
out.write("\n");
out.flush();
}catch(IOExceptione1){
//TODOAuto-generatedcatchblock
e1.printStackTrace();
}
}
publicStringclientRequest()
{
Stringmsg=null;
try{
in=newBufferedReader(newInputStreamReader(cs.getInputStream()));
msg=in.readLine();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnmsg;
}
publicThreadServer(Socketincoming)
{
this.cs=incoming;
setTicket();
}
publicvoidsocketClose()
{
try{
cs.close();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
publicvoidrun()
{
Stringmsg=null;
msg=clientRequest();
String[]tokens=msg.split("\\|");
switch(tokens[0])
{
case"search":
Stringresult="Tickets";
result+=ticket;
sendMessage(result);
break;
case"buy":
ticket=sale(tokens[1],ticket);
sendMessage(tokens[1]);
}
}
publicsynchronizedArrayListsale(Stringc,ArrayListticket)
{
ticket.remove(c);
System.out.println("顾客购买的票号为:
"+c);
returnticket;
}
}
2.客户端编写的关键技术点
为实现客户端与服务端的正常通信,通信端口需要与服务端开放的端口保持一致。
为了避免通道堵塞,需要为读和写两个操作单独开两个线程。
客户端对服务端的请求需要按照编写的简单协议的要求来进行。
以下为客户端的代码:
packagebuytickets;
importjava.io.IOException;
import.Socket;
import.UnknownHostException;
importjava.util.Scanner;
importsocket.ClientSocket;
publicclassBuyerClient{
publicBuyerClient()throwsUnknownHostException,IOException
{
while(true)
{
System.out.println("欢迎选票,请选择相应操作:
");
System.out.println("1.查询2.购票");
Socketclientsocket=newSocket("localhost",1234);
ClientSocketclient=newClientSocket(clientsocket);
Scannersc=newScanner(System.in);
intchoice=sc.nextInt();
switch(choice)
{
case1:
{
Stringmsg=null;
if(client.sendMessage("search"))
{
msg=client.serverResponse();
}
System.out.println("票号:
"+msg);
break;
}
case2:
{
System.out.println("请选择座位号:
");
sc=newScanner(System.in);
Stringticketnumber=sc.nextLine();
Stringresult1="buy|"+ticketnumber;
if(client.sendMessage(result1))
{
System.out.println("您购买的票号为:
"+client.serverResponse());
}
break;
}
}
}
}
publicstaticvoidmain(String[]args)throwsUnknownHostException,IOException
{
newBuyerClient();
}
}
客户端中socket类的封装:
packagesocket;
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
import.Socket;
publicclassClientSocket{
privateSocketcs;
privateBufferedReaderin;
privateBufferedWriterout;
publicClientSocket(Socketi)
{
this.cs=i;
}
publicbooleansendMessage(Stringmsg)
{
booleanflag=false;
try{
out=newBufferedWriter(newOutputStreamWriter(cs.getOutputStream()));
}catch(IOExceptione1){
//TODOAuto-generatedcatchblock
e1.printStackTrace();
}
try{
out.write(msg);
out.write("\n");
out.flush();
flag=true;
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnflag;
}
publicStringserverResponse()
{
Stringmsg=null;
try{
in=newBufferedReader(newInputStreamReader(cs.getInputStream()));
msg=in.readLine();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnmsg;
}
publicvoidstreamClose()
{
try{
in.close();
out.close();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
三、运行结果截图
1.运行服务端
服务端在等待客户端连接,如图一:
2.运行客户端
3.执行查询票号操作
4.购票
4、小组成员分工
成员一:
负责客户端的编写
成员二:
负责服务端的编写
5、设计难点及解决问题的收获
设计难点:
1.在网络编程中读和写操作经常发生堵塞。
2.客户端的请求报头。
3.服务端的协议解析及同步代码块的编写。
4.对输入输出流的封装。
收获:
通过此次网络编程,对网络数据传输的过程有了更进一步的了解和加深,对线程的同步机制有着清晰的认识,大大提高了编程能力。