1.1、TCP,同步版本的Server:
package com.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* TCP的网络编程,服务器
* @author Feng
*
*/
public class TCPTestServer{
public static void main(String[] args) throws IOException, InterruptedException{
//服务器开始监听6666号端口
//从启动上说,必须要先启动服务器端程序
ServerSocket ss = new ServerSocket(6666);
//因为服务器需要不断等待连接,所以死循环等待
while(true){
System.out.println("等待连接申请中···");
//接受链接申请,这样写只接受一个连接,这个方法是阻塞式的,如果没有任何连接申请就会一直等待
Socket s = ss.accept();
if(s.isConnected()){
System.out.println("OK!!!!!");
//使用输入流接受客户端传入的信息
InputStream stream = s.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
//注意,像这种输入流的方式属于同步输入,连接成功后如果客户端不传送东西,这里的输入流会一直等待,导致其他连接申请被搁置
System.out.println(reader.readLine());
}else{
System.out.println("NO!!");
}
}
}
}
1.2、TCP,同步版本的Client:
package com.socket;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* TCP网络编程,客户端
* @author Feng
*
*/
public class TCPTestClient {
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException{
//客户端申请连接到 127.0.0.1:6666
//客户端会给这边的socket随机分配端口号,具体是多少并不重要
Socket s = new Socket("127.0.0.1", 6666);
//连接成功之后,可以通过管道来进行通话,使用输出管道
//这里的等待模拟:线连接,但是迟迟不发送信息,这个时候这个链接会被该客户端独占
Thread.sleep(10000);
OutputStream stream = s.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
writer.write("SHTI!!!!你妹!!!!!");
writer.flush();
writer.close();
s.close();
}
}
2、TCP,多线程的图片接收服务器
package com.socket;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPJpgGetter {
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(6666);
while(true){
Socket s = ss.accept();
new Thread(new Getter(s)).start();
}
}
}
/**
* 多线程的图片接收类
* 服务器端开启多个线程用于接收传送过来的图片
*/
class Getter implements Runnable{
private Socket s = null;
public Getter(Socket s){
this.s = s;
}
@Override
public void run() {
try {
String info = s.getInetAddress().toString();
//从socket读取数据的输入流
InputStream getter = s.getInputStream();
//回传数据的输出流
OutputStream sender = s.getOutputStream();
//为了避免文件名重复的覆盖,使用编号
int count = 1;
File temp = new File("D:/" + info + "(" + count + ").jpg");
while(temp.exists()){
//这里的处理不是很严谨,还是有可能会导致文件覆盖
temp = new File("D:/" + info + "(" + (++count) + ").jpg");
}
System.out.println("接收到来自:" + info + "的传送请求,存储名为:" + temp.getName());
//创建文件并写入到磁盘的输出流
FileOutputStream fileWriter = new FileOutputStream(temp);
byte[] buf = new byte[1024];
int len;
while((len=getter.read(buf)) != -1){
//写文件的时候要注意写的长度
fileWriter.write(buf, 0, len);
}
sender.write("上传成功".getBytes("UTF-8"));
fileWriter.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.1、UDP,同步版本的“Server”:
package com.socket;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* UDP的“服务器”,事实上UDP并没有明确地服务器和客户端的分类,因为是不安全连接,要做的就是确定目标IP和端口号,然后直接发送就好了
* @author Feng
*
*/
public class UDPTestServer {
public static void main(String[] args) throws IOException{
byte buf[] = new byte[1024];
//DatagramPacket用来存放需要发送或者要接收的数据
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//DatagramSocket就是UDP方式的socket,为服务器指定端口号6666
DatagramSocket ds = new DatagramSocket(6666);
while(true){
//receive方法是阻塞式方法,等待接收数据
ds.receive(dp);
//获取发送源的IP地址和端口号,在发送端由于没有指定端口号,这里看到的端口是系统随机分配的端口
System.out.println("收取到来自 " + dp.getAddress() + ":" + dp.getPort() + " 的信息:");
//以字符串的形式获取数据并打印
System.out.println("字符串:" + new String(buf, 0, dp.getLength()));
//接受传送过来的信息,信息已经存储在buf之中
ByteArrayInputStream in = new ByteArrayInputStream(buf);
DataInputStream din = new DataInputStream(in);
System.out.println("数字:" + din.readLong());
System.out.println();
}
}
}
3.2、UDP,同步版本的“Client”:
package com.socket;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UDPTestClient {
public static void main(String[] args) throws IOException{
byte[] buf = new String("你好!~~").getBytes();
//将一个long类型数据转换成byte[];
long num = 123412341234L;
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(out);
dout.writeLong(num);
byte[] buf2 = out.toByteArray();
System.out.println(buf2.length);
//新建socket的时候如果不指定端口号,那系统将为其默认指定一个地址,作为发送方,这个socket不需要指定端口
DatagramSocket ds = new DatagramSocket();
DatagramPacket dp = null;
//DatagramPacket是UDP模式下传输信息的媒介
//指定目的地址为127.0.0.1:6666
dp = new DatagramPacket(buf, buf.length,
new InetSocketAddress("127.0.0.1", 6666));
ds.send(dp);
dp = new DatagramPacket(buf2, buf2.length,
new InetSocketAddress("127.0.0.1", 6666));
ds.send(dp);
ds.close();
}
}
4、UDP聊天小程序
package com.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
/**
* 两个线程,定义一个接受和一个发送端
* 写入目标机器的IP地址和端口号即可通信
* 中文问题:我的MyEclipse默认编码是UTF-8,运行的时候要在Run-Run Configuration-Common-指定GBK,否则会出现中文乱码问题
* @author Feng
*/
public class UDPTalker {
public static void main(String[] args) throws IOException{
InetAddress myAdd = InetAddress.getLocalHost();
System.out.println("本机地址:" + myAdd);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入目标机器IP地址:");
String ipAdd = reader.readLine();
System.out.println("请输入目标机器端口号:");
int port = Integer.parseInt(reader.readLine());
DatagramSocket sender = new DatagramSocket();
DatagramSocket listener = new DatagramSocket(6666);
//消息发送目的地
InetSocketAddress address = new InetSocketAddress(ipAdd, port);
new Thread(new Send(sender, address)).start();
new Thread(new Listen(listener)).start();
}
}
/**
* 发送线程,接受键盘输入,并将消息发往指定的地址
* @author Feng
*
*/
class Send implements Runnable{
private DatagramSocket ds = null;
private InetSocketAddress address = null;
public Send(DatagramSocket ds, InetSocketAddress address){
this.ds = ds;
this.address = address;
}
@Override
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line = null;
try {
while((line=reader.readLine()) != null){
byte[] temp = line.getBytes("UTF-8");
//发送数据包,指定了发送的内容以及目的地
DatagramPacket dp = new DatagramPacket(temp, temp.length, address);
ds.send(dp);
if("exit".equals(line)){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 接收线程,等待接收消息并显示
* @author Feng
*
*/
class Listen implements Runnable{
private DatagramSocket ds = null;
public Listen(DatagramSocket ds){
this.ds = ds;
}
@Override
public void run() {
try {
while(true){
byte[] temp = new byte[1024];
//接收数据包,缓存大小为1K
DatagramPacket dp = new DatagramPacket(temp, temp.length);
ds.receive(dp);
String address = dp.getAddress().getHostAddress() + "-" + dp.getPort();
String data = new String(dp.getData(), 0, dp.getLength(), "UTF-8");
System.out.println(address + ": " + data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}