socket编程(Java实现)
主要是前段时间学习的网络知识的基于TCP与UDP编程,Java实现简单的大小写字母的转化,该文主要参考:
https://blog.csdn.net/yjp19871013/article/details/53537398
UDP服务端代码:
public class ToUpperUDPServer {
//服务器的IP
public static final String SERVER_IP = "127.0.0.1";
//服务器端的端口号 最好是大于2000 不要选取那些特殊的端口号 Oracle:1521 MySQL:3306 Tomcat:8080
public static final int SERVER_PORT = 10005;
//最大的传输字节数
public static final int MAX_BYTES = 1024;
//UDP使用DatagramSocket发送数据包
private DatagramSocket serverSocket;
/**
* 启动服务器
* @param serverIp 服务器的IP地址
* @param serverPort 服务器的端口号
*/
public void startServer(String serverIp, int serverPort){
try {
//创建DatagramSocket
InetAddress serverAddr = InetAddress.getByName(serverIp);
serverSocket = new DatagramSocket(serverPort, serverAddr);
//创建接受服务的对象
byte[] recvBuf = new byte[MAX_BYTES];
DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
//死循环,一直运行服务器
while(true){
System.out.println("服务端正在接收数据,接收的数据包为:"+recvPacket);
//接受数据,会在这里堵塞,直达数据到来
serverSocket.receive(recvPacket);
String receStr = new String(recvPacket.getData(), 0 , recvPacket.getLength());
//获取连接端的IP和端口号port
InetAddress clientAddr = recvPacket.getAddress();
int clientPort = recvPacket.getPort();
//回传数据
String upperStr = receStr.toUpperCase();
byte[] sendBuf = upperStr.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, clientAddr, clientPort);
System.out.println("服务端正在发送数据,发送的数据包为:"+sendPacket);
//服务器Socket 发送数据
serverSocket.send(sendPacket);
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
ToUpperUDPServer server = new ToUpperUDPServer();
server.startServer(SERVER_IP, SERVER_PORT);
}
}
UDP客户端代码:
public class ToUpperUDPClient {
//创建连接的DatagramSocket
private DatagramSocket clientSocket;
public String toUpperRemote(String serverIp, int serverPort, String str){
String recvStr = "";
try {
//创建 UDP socket
clientSocket = new DatagramSocket();
byte[] sendBuf = str.getBytes();
InetAddress serverAddr = InetAddress.getByName(serverIp);
DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, serverAddr, serverPort);
clientSocket.send(sendPacket);
System.out.println("客户端正在发送数据,发送的数据包为:" + sendPacket);
//接收服务器的响应
byte[] recvBuf = new byte[ToUpperUDPServer.MAX_BYTES];
DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
clientSocket.receive(recvPacket);
System.out.println("客户端正在接收服务器的响应,接收的数据包为:" + recvPacket);
//显示响应
recvStr = new String(recvPacket.getData(), 0 , recvPacket.getLength());
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(null != clientSocket){
clientSocket.close();
clientSocket = null;
}
}
return recvStr;
}
public static void main(String[] args) {
ToUpperUDPClient client = new ToUpperUDPClient();
String recvStr = client.toUpperRemote(ToUpperUDPServer.SERVER_IP, ToUpperUDPServer.SERVER_PORT, "aaaAAAbbbBBBcccCCC");
System.out.println("客户端收到的数据:" + recvStr);
}
}
TCP服务端有三种模式:
1、基于TCP协议阻塞式服务
public class ToUpperTCPBlockServer {
//服务端的IP地址
public static final String SERVER_IP = "127.0.0.1";
//服务端的端口号
public static final int SERVER_PORT = 10005;
//请求终结字符串
public static final char REQUEST_END_CHAR = '#';
/***
* 开启服务
* @param serverIp 服务端ip地址
* @param serverPort 服务端端口号
*/
public void startServer(String serverIp, int serverPort){
try {
//创建服务器地址对象
InetAddress serverAddr = InetAddress.getByName(serverIp);
//Java提供了ServerSocket作为服务器
//楼主使用了Java的自动关闭的语法, 这个自动关闭语法是JDK1.7中的,我这里是正常写法
ServerSocket serverSocket = new ServerSocket(SERVER_PORT, 5, serverAddr);
while(true){
StringBuilder recvStrBuilder = new StringBuilder();
//有客户端向服务器发起tcp连接时,accept会返回一个Socket
//该Socket的対端就是客户端的Socket
//具体过程可以查看TCP三次握手过程
Socket connection = serverSocket.accept();
InputStream in = connection.getInputStream();
//读取客户端的请求字符串,请求字符以#结尾
for(int c=in.read(); c!=REQUEST_END_CHAR; c=in.read()){
recvStrBuilder.append((char) c);
}
recvStrBuilder.append("#");
String recvStr = recvStrBuilder.toString();
//向客户端写出处理过的字符串
OutputStream os = connection.getOutputStream();
os.write(recvStr.toUpperCase().getBytes());
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
ToUpperTCPBlockServer server = new ToUpperTCPBlockServer();
System.out.println("服务器端开始接收请求...");
server.startServer(SERVER_IP, SERVER_PORT);
}
}
2、基于TCP的并发服务器
public class ToUpperTCPThreadServer {
//服务器对外的ip
public static final String SERVER_IP = "127.0.0.1";
//服务器端口号
public static final int SERVER_PORT = 10005;
//请求中介字符串
public static final char REQUEST_END_CHAR = '#';
/***
* 开启服务
* @param serverIp 服务端ip
* @param serverPort 服务端端口号
*/
public void startServer(String serverIp, int serverPort){
try {
InetAddress serverAddr = InetAddress.getByName(serverIp);
ServerSocket serverScoket = new ServerSocket(SERVER_PORT, 5 ,serverAddr);
//创建线程池
Executor executor = Executors.newFixedThreadPool(100);
//保持服务一直处于开启的状态
while(true){
final StringBuilder recvStrBuilder = new StringBuilder();
//有客户向服务器发起TCP连接时,accept会返回一个socket
//该socket的对端就是客户端的socket
//具体情况可以查看socket的三次握手情况
final Socket connection = serverScoket.accept();
//利用线程池,启动线程
executor.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Socket conn = connection;
try {
InputStream in = conn.getInputStream();
for(int c=in.read(); c!=REQUEST_END_CHAR; c=in.read()){
recvStrBuilder.append((char) c);
}
recvStrBuilder.append('#');
String resvStr = recvStrBuilder.toString();
////向客户端写出处理后的字符串
OutputStream os = connection.getOutputStream();
os.write(resvStr.toUpperCase().getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(conn != null){
try {
conn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
ToUpperTCPThreadServer server = new ToUpperTCPThreadServer();
server.startServer(SERVER_IP, SERVER_PORT);
}
}
3、第三种
public class ToUpperTCPNonBlockServer {
//服务器对外的ip
public static final String SERVER_IP = "127.0.0.1";
//服务器端口号
public static final int SERVER_PORT = 10005;
//请求中介字符串
public static final char REQUEST_END_CHAR = '#';
/**
* 开启服务
* @param serverIp 服务器对外的ip
* @param serverPort 服务器端端口号
*/
public void startServer(String serverIp, int serverPort){
try {
//使用NIO 需要用到ServerSocketChannel 其中包含一个serverSocket对象
ServerSocketChannel serverChannel = ServerSocketChannel.open();
//创建地址对象
InetSocketAddress localAddr = new InetSocketAddress(SERVER_IP,SERVER_PORT);
//服务器绑定地址
serverChannel.bind(localAddr);
//设置为非堵塞
serverChannel.configureBlocking(false);
//注册到Selector 会ServerSocket的accept
//我们用Selector监听accept是否返回
//当调用accept卡伊返回时,会得到通知
//注意是可以返回,还需要调用accept
Selector selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
//服务一直处于启动状态,所以这个是死循环
while(true){
//调用select,阻塞在这里,直到有注册的channel满足条件
selector.select();
//如果走到这里,有符合条件的channel
//可以通过selector.selectedKeys().iterator()得到符合条件的迭代器
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
//处理得到的keys
while(keys.hasNext()){
//取出一个key 并移除
SelectionKey key = keys.next();
keys.remove();
try{
if(key.isAcceptable()){
//有accept返回,取出可以使用的channel
ServerSocketChannel server = (ServerSocketChannel) key.channel();
//调用accept三次握手 返回与客户端可以通信的channel
SocketChannel channel = server.accept();
//将该channel 置为非堵塞
channel.configureBlocking(false);
//注册此selector 当可读或可写时将得到通知,select返回
channel.register(selector, SelectionKey.OP_READ);
}else if(key.isReadable()){
//有channel可读 取出可读的channel
SocketChannel channel = (SocketChannel) key.channel();
//创建读取缓冲区,一次读取1024字节
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
//锁住缓冲区,缓冲区的大小将固定
buffer.flip();
//附件上buffer 供写出使用
key.attach(buffer);
key.interestOps(SelectionKey.OP_WRITE);
}else if(key.isWritable()){
//有channel可写,取出可写的channel
SocketChannel channel = (SocketChannel) key.channel();
//取出可读时设置的缓冲区
ByteBuffer buffer = (ByteBuffer) key.attachment();
//将缓冲区的指针移动到缓冲区开始的位置
buffer.rewind();
//读取为String
String recv = new String(buffer.array());
//清空缓冲区
buffer.clear();
buffer.flip();
//写回数据
byte[] sendByte = recv.toUpperCase().getBytes();
channel.write(ByteBuffer.wrap(sendByte));
//变为等待者
key.interestOps(SelectionKey.OP_READ);
}
}catch(Exception e){
key.cancel();
key.channel().close();
e.printStackTrace();
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main (String[] args){
ToUpperTCPBlockServer server = new ToUpperTCPBlockServer();
server.startServer(SERVER_IP, SERVER_PORT);
}
}
TCP客户端:
public class ToUpperTCPClient {
//客户端的请求的 TCP socket
private Socket clientSocket;
public String toUpperRemote(String serverIp, int ServerPort, String str){
StringBuilder recvStrBuilder = new StringBuilder();
try {
//创建连接服务器的socket
clientSocket = new Socket(serverIp, ServerPort);
//写出请求的字符串
OutputStream os = clientSocket.getOutputStream();
os.write(str.getBytes());
//读取服务器响应
InputStream in = clientSocket.getInputStream();
for(int c=in.read(); c!='#'; c=in.read()){
recvStrBuilder.append((char) c);
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(clientSocket != null){
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return recvStrBuilder.toString();
}
public static void main(String[] args) {
ToUpperTCPClient client = new ToUpperTCPClient();
String recvStr = client.toUpperRemote(ToUpperTCPBlockServer.SERVER_IP, ToUpperTCPBlockServer.SERVER_PORT,"aaaAAAbbbBBBcccCCC" + ToUpperTCPBlockServer.REQUEST_END_CHAR);
System.out.println("收到:" + recvStr);
}
}
socket编程(Java实现)的更多相关文章
- UDP协议网络Socket编程(java实现C/S通信案例)
我的博客园:https://www.cnblogs.com/chenzhenhong/p/13825286.html 我的CSDN博客:https://blog.csdn.net/Charzous/a ...
- socket编程-java
一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...
- Java:基于TCP协议网络socket编程(实现C/S通信)
目录 一.前言:TCP原理简介 二.Socket编程通信 三.TCP服务器端(具体代码) 四.TCP客户端(具体代码) 五.通信效果演示 六."创意"机器人:价值一个亿的AI核心代 ...
- java多线程实现TCP网络Socket编程(C/S通信)
目录 开篇必知必会 一.多线程技术 二.实现多线程接收 1.单线程版本 2.多线程版本 三.多线程与进程的关系 四.客户端界面完整代码 五.多线程通信对比 最后 开篇必知必会 在前一篇<Java ...
- java socket编程(li)
一.网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输.在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以 ...
- 【JAVA】Socket 编程
对于Java Socket编程而言,有两个概念,一个是ServerSocket,一个是Socket.服务端和客户端之间通过Socket建立连接,之后它们就可以进行通信了.首先ServerSocket将 ...
- java socket编程(网络编程)
一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...
- JAVA Socket 编程学习笔记(二)
在上一篇中,使用了 java Socket+Tcp/IP 协议来实现应用程序或客户端--服务器间的实时双向通信,本篇中,将使用 UDP 协议来实现 Socket 的通信. 1. 关于UDP UDP协 ...
- JAVA Socket 编程学习笔记(一)
1. Socket 通信简介及模型 Java Socket 可实现客户端--服务器间的双向实时通信.java.net包中定义的两个类socket和ServerSocket,分别用来实现双向连接的cli ...
- Java Socket编程
Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术. ...
随机推荐
- RobotFrameWork--selenium2模拟chrome的user agent
${options}= Evaluate sys.modules['selenium.webdriver'].ChromeOptions() sys, selenium.webdriver ${opt ...
- linux中的C里面使用pthread_mutex_t锁(转载)
转自:http://blog.csdn.net/w397090770/article/details/7264315 linux下为了多线程同步,通常用到锁的概念. posix下抽象了一个锁类型的结构 ...
- 金融事业部QA培训体系
此文已由作者夏君授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 引言 总结2015,放眼2016,纵观整个互联网圈,人才依然是业务成功的第一要素,在网易,我想也是这样 ...
- 关于MYSQL编辑乱码问题
今天在SQLyog中编写表数据时突然出现一个bug,在此记录分享一下. 使用MySQL数据库时,讲中文插入到数据苦衷进行刷新后全部都变成了乱码问号,如下图中studentName列: 产生乱码是因为没 ...
- [Swift通天遁地]一、超级工具-(2)制作美观大方的环形进度条
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- Akka源码分析-CircuitBreaker(熔断器)
熔断器,在很多技术栈中都会出现的一种技术.它是在分布式系统中提供一个稳定的阻止嵌套失败的机制. 该怎么理解呢?简单来说,在分布式环境中,如果某个计算节点出现问题,很容易出现失败的逆向传到或整个系统的雪 ...
- java-使用反射实现ORM映射
自定义两个注解 package com.moon.ROM; import java.lang.annotation.ElementType; import java.lang.annotation.R ...
- 2018SCin tsyzDay1 模拟赛-模拟
预计得分:70+0+0+100+100+100+100=470 实际得分:70+0+0+30+100+0+40=240 第一天就被模拟虐爆qwq T1 https://www.luogu.org/pr ...
- python爬虫爬取腾讯招聘信息 (静态爬虫)
环境: windows7,python3.4 代码:(亲测可正常执行) import requests from bs4 import BeautifulSoup from math import c ...
- Unix\Linux | 总结笔记 | 邮件发送
实验:在本地实现不同用户收发邮件 #root发送邮件 #stu 收邮件 #stu 查看邮件 并回复邮件 #root 查看stu回复的邮件