打开服务器套接字后,我想访问它的 IP 地址(其他人可以用来连接的 IP 地址)。当我打电话时
ServerSocket seso = new ServerSocket(port);
System.out.println(seso.getInetAddress());
Run Code Online (Sandbox Code Playgroud)
它显示(0.0.0.0/0.0.0.0),这只是网络掩码。我想得到的是套接字实际绑定的IP,例如130.75.22.12(或类似的东西)。
我正在开发一款游戏,并正在考虑进入网络领域。我从事编程工作已有大约 5 年,最近 2 年开始从事游戏开发。我只是利用自己的时间在网上和书本上真正学习。我计划为 Amazon AWS EC2 制作一个 java 服务器,但我只是想知道 MMO 如何处理每个时间点的多个玩家。
这仅仅是服务器的力量吗?我不是在寻找代码或任何东西,只是在寻找服务器的一般工作方式。
服务器是否只对所有玩家和数万或数十万个对象进行所有计算,然后在每个周期发送和接收数千个数据包?对于一台计算机来说似乎要处理很多事情,但它确实是一台服务器。
我有一个java.net.ServerSocket用于侦听连接。我正在使用它的accept()方法来从客户端获取连接,然后适当地处理它们。我希望不断倾听客户的声音,永远不要让他们无法使用。目前我有类似的代码:
ServerSocket serverSocket = ...
while (shouldBeListening) {
handleClient(serverSocket.accept());
}
Run Code Online (Sandbox Code Playgroud)
该handleClient方法可能需要少量时间(小于十分之一毫秒)。我担心在ServerSocket.accept()方法返回和再次调用之间可能会错过连接请求。解决此问题的最佳方法是什么?
编辑:我实现它的方式目前在handleClient方法中创建了一个新线程,但即使这样也需要时间(特别是因为这是在Raspberry Pi上运行的),我担心如果handleClient在执行方法时请求连接那么它可能会被拒绝,因为accept()没有被运行。
据我所知,IPv6 环回是::1. 所以当我尝试这个时:
//includes of all needed headers in one place
#include <include.h>
#define BACKLOG 10
int main(int argc, char const *argv[])
{
if (argc != 2)
{
die("Usage: %s <port>\n", argv[0]);
}
int port = atoi(argv[1]);
int numOfClient = 0;
int sockfd = socket(AF_INET6, SOCK_STREAM, 0);
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET6;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(port);
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("bind");
}
else
{
printf("[+]bind\n");
}
if (listen(sockfd, BACKLOG) < …Run Code Online (Sandbox Code Playgroud) 我有一些生成套接字绑定的 Java 代码。很难提供一个最小的示例,因为这是 Web 框架的一部分,但它在某些时候有效地执行了此检查。
private static boolean portInUse(int port) {
// try to bind to this port, if it succeeds the port is not in use
try (ServerSocket socket = new ServerSocket(port)) {
socket.setReuseAddress(true);
return false;
} catch (IOException e) {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
我可以看到,如果我使用同一端口运行两个不同的 Java 进程,它们都会落入第一个条件并返回false,因此两者都能够绑定到同一端口。我已经阅读了一些相关的套接字问题和解释,例如 this,但它们似乎听起来像是我指定的选项不可能实现这一点。看看setReuseAddress它的实现似乎只SO_REUSEADDR在套接字上设置。
我可以看到一个进程最终有一个套接字,就像ServerSocket[addr=0.0.0.0/0.0.0.0,localport=56674]在调试器中一样。如果我运行类似的命令,sudo lsof -n -i | grep -e LISTEN -e ESTABLISHED | grep 56674我可以看到两个进程绑定到同一端口:
java 68863 natdempk 1256u IPv4 …Run Code Online (Sandbox Code Playgroud) 我们目前遇到在Windows上运行的自编服务器应用程序的问题(在不同版本上发生).服务器侦听TCP端口,接受连接,交换一些数据,然后再次关闭连接.大约有100个客户端不时连接.
有时服务器停止工作:日志文件显示仍然接受连接,但在第一次读取尝试时发生套接字错误(10054 - 由对等方重置连接).我不认为这是一个客户问题,因为它突然停止为所有客户工作.
现在我们发现,我们的旧服务器软件也出现了同样的问题,甚至用另一种编程语言编写.所以它在我们的程序中似乎不是一个错误 - 我认为它必须是某种操作系统/防火墙问题?当然,防火墙已经停用,但尚未解决问题.
任何想法在哪里研究?Wireshark日志即将推出..
摘自日志(时间戳,线程ID,消息)
11:37:56.137 T#3960 Connection from 10.21.13.3
11:37:56.138 T#3960 Client Exception: Socket Error # 10054
Connection reset by peer.
11:37:56.138 T#3960 ClientDisconnected
11:38:00.294 T#4144 Connection from 10.21.13.3
Run Code Online (Sandbox Code Playgroud)
您可以看到异常几乎在接受连接的同时发生,在这种情况下,客户端会在几秒钟后重新连接.
据我所知,GAE不支持使用原始TCP/IP套接字,即java.net.ServerSocket.有没有其他众所周知的云服务我可以使用它?比如Amazon EC2?
我的客户端应用程序需要与服务器的永久TCP连接...
非常感谢STeN
我有一些看起来与此类似的java代码:
private void startServer() throws IOException {
URLClassLoader classloader = null;
System.out.println("Opening server socket for listening on " + PORT_NUMBER);
try {
server = new ServerSocket(PORT_NUMBER);
server.setSoTimeout(10000);
connected = true;
System.out.println("Server is now listening on port " + PORT_NUMBER);
} catch (IOException e) {
System.err.println("Could not start server on port " + PORT_NUMBER);
e.printStackTrace();
connected = false;
}
while (connected) {
// Incoming request handler socket.
Socket socket = null;
try {
System.out.println("Waiting for client connection...");
// Block waiting for …Run Code Online (Sandbox Code Playgroud) 我正在创建一个多客户端聊天服务器,我相信它会工作(纠正我,如果我错了),我有一个问题,在客户端连接到的套接字是空的,所以无法创建连接因为我使用if(Socket!= null)所以我没有得到错误,但我会快速解释我的布局.服务器以名为(LaunchServer)的入门类启动,该类使用类对象ClientConnector作为Minecraft,然后启动方法runServer().这是这个类的代码:
public class LaunchServer
{
public static void main(String[] args)
{
System.out.println("[Info] Running");
ClientConnector Minecraft = new ClientConnector();
Minecraft.runServer();
}
}
Run Code Online (Sandbox Code Playgroud)
这很简单.这将我们带到ClientConnector类.这里我们从方法runServer()开始.马上我们有一个try catch块.在该块中,我们打印一条消息,服务器正在尝试连接到端口1337.然后我们创建一个名为serversocket的新ServerSocket.然后我们向控制台发送一条消息说我们已经绑定了端口并且我们正在等待连接.虽然如此,我们创建一个新的Socket套接字,它等于ServerSocket.accept(); 天哪,他妈的.继承人的代码.你知道它做了什么......
import java.util.ArrayList;
import java.net.*;
import java.io.*;
public class ClientConnector
{
public static ArrayList<Socket> Connections = new ArrayList<Socket>();
public static void runServer()
{
try
{
System.out.println("[Info] Attempting to bind to port 1337.");
@SuppressWarnings("resource")
ServerSocket serversocket = new ServerSocket(1337);
System.out.println("[Info] Bound to port 1337.");
System.out.println("[Info] Waiting for client connections...");
while(true)
{
Socket socket = serversocket.accept();
new ClientHandler(socket).start(); …Run Code Online (Sandbox Code Playgroud) 我正在编写一个示例Android应用程序,它将创建一个简单的http服务器,但面临一个小问题.
这是我的MainActivity
public class MainActivity extends Activity {
private ServerSocket ss;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Init();
}
private void Init() {
Button btnStart = (Button) findViewById(R.id.btn_start);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
try{
if(ss != null){
return;
}
ss = new ServerSocket(8080);
while (true) {
Socket s = ss.accept();
System.err.println("Client accepted");
new Thread(new SocketProcessor(s)).start();
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}).start(); …Run Code Online (Sandbox Code Playgroud) serversocket ×10
java ×7
sockets ×5
networking ×2
tcp ×2
amazon-ec2 ×1
android ×1
c ×1
connection ×1
ipv6 ×1
macos ×1
multiplayer ×1
null ×1