Echo Socket例子项目

socket编程入门实践——基于TCP的echo服务器/客户端 最近在学习Linux网络编程,参考《TCP/IP网络编程》写下这个socket编程示例——基于TCP的echo服务器/客户端。echo服务器,顾名思义就是将收到的客户端数据原封不动地传回客户端。 无论多么复杂的TCP服务器,其函数调用顺序几乎都是socket -> bind -> listen -> accept -> read/write -> close,因此掌握这些基本函数的使用方法是很重要的。以下是基于TCP的echo服务器的完整代码(附带详细注释): #include 阅读详情

  这个例子提供如下:

      定义必要的配置sockets的参数的一个简单的用户接口。

     service逻辑对于一个见到的echo服务重复这接收到的字节返回给发送者。

    模块化原生代码片段来对于Android的原生层方便socket编程。

   一个面向连接的socket通信例子。

   一个无连接的通信例子。

   一个本地的socket通信例子。

  建立一个Echo的Android项目。

 

    Abstractt Echo Activity:

   为了重复利用者普通的功能,将会创建一个抽象的activity类在定义这时间activity之前。使用Project Explorer 视图,打开src目录,旋转com.apress.echo包,和选择new-》class。设置名字为AbstractEchoActivity和点击这完成按钮。该新文件的内容如下:

package com.apress.echo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
/**
* Abstract echo activity object.
*
* @author Onur Cinar
*/
public abstract class AbstractEchoActivity extends Activity implements
OnClickListener {
/** Port number. */
protected EditText portEdit;
/** Server button. */
protected Button startButton;
/** Log scroll. */
protected ScrollView logScroll;
/** Log view. */
protected TextView logView;
/** Layout ID. */
private final int layoutID;
/**
* Constructor.
*
* @param layoutID
Communication
* layout ID.
*/
public AbstractEchoActivity(int layoutID) {
this.layoutID = layoutID;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layoutID);
portEdit = (EditText) findViewById(R.id.port_edit);
startButton = (Button) findViewById(R.id.start_button);
logScroll = (ScrollView) findViewById(R.id.log_scroll);
logView = (TextView) findViewById(R.id.log_view);
startButton.setOnClickListener(this);
}
public void onClick(View view) {
if (view == startButton) {
onStartButtonClicked();
}
}
/**
* On start button clicked.
*/
protected abstract void onStartButtonClicked();
/**
* Gets the port number as an integer.
*
* @return port number or null.
*/
protected Integer getPort() {
Integer port;
try {
port = Integer.valueOf(portEdit.getText().toString());
} catch (NumberFormatException e) {
port = null;
}
return port;
}
/**
* Logs the given message.
*
* @param message
* log message.
*/

protected void logMessage(final String message) {
runOnUiThread(new Runnable() {
public void run() {
logMessageDirect(message);
}
});
}
/**
* Logs given message directly.
*
* @param message
* log message.
*/
protected void logMessageDirect(final String message) {
logView.append(message);
logView.append("\n");
logScroll.fullScroll(View.FOCUS_DOWN);
}
/**
* Abstract async echo task.
*/
protected abstract class AbstractEchoTask extends Thread {
/** Handler object. */
private final Handler handler;
/**
* Constructor.
*/
public AbstractEchoTask() {
handler = new Handler();
}
/**
* On pre execute callback in calling thread.
*/
protected void onPreExecute() {
startButton.setEnabled(false);
logView.setText("");
}
public synchronized void start() {
onPreExecute();
super.start();
}
public void run() {
onBackground();
handler.post(new Runnable() {
public void run() {
onPostExecute();
}
});
}
/**
* On background callback in new thread.
*/
protected abstract void onBackground();
/**
* On post execute callback in calling thread.
*/
protected void onPostExecute() {
startButton.setEnabled(true);
}
}
static {
System.loadLibrary("Echo");
}

   AbstractEchoActivity,除了处理houskeeping任务外例如绑定这用户接口组件,提供一个简单的线程实现能够使应用程序来执行这网络操作在单独的线程而不是UI线程。

  Echo项目的字符串资源:

  <resources>
<string name="app_name">Echo</string>
<string name="title_activity_echo_server">Echo Server</string>
<string name="port_edit">Port Number</string>
<string name="start_server_button">Start Server</string>
<string name="title_activity_echo_client">Echo Client</string>
<string name="ip_edit">IP Address</string>
<string name="start_client_button">Start Client</string>
<string name="send_button">Send</string>
<string name="message_edit">Message</string>
<string name="title_activity_local_echo">Local Echo</string>
<string name="local_port_edit">Port Name</string>

  原生的Echo模块:

  这原生的echo模块将提供者原生socket接口方法对于这Java应用程序的实现。使用Project Explorer,展开jni目录对于原生源文件,和双击这Echo.cpp C++源文件。代替它的内容如下:

  // JNI
#include <jni.h>
// NULL
#include <stdio.h>
// va_list, vsnprintf
#include <stdarg.h>
// errno
#include <errno.h>
// strerror_r, memset
#include <string.h>
// socket, bind, getsockname, listen, accept, recv, send, connect
#include <sys/types.h>
#include <sys/socket.h>
// sockaddr_un
#include <sys/un.h>
// htons, sockaddr_in
#include <netinet/in.h>
// inet_ntop
#include <arpa/inet.h>
// close, unlink
#include <unistd.h>
Download at http://www.pin5i.com/
216 CHAPTER 8: POSIX Socket API: Connection-Oriented Communication
// offsetof
#include <stddef.h>
// Max log message length
#define MAX_LOG_MESSAGE_LENGTH 256
// Max data buffer size
#define MAX_BUFFER_SIZE 80
/**
* Logs the given message to the application.
*
* @param env JNIEnv interface.
JNIEnv* env,
jobject obj,
const char* format,
...)
{
// Cached log method ID
static jmethodID methodID = NULL;
// If method ID is not cached
if (NULL == methodID)
{
// Get class from object
jclass clazz = env->GetObjectClass(obj);
// Get the method ID for the given method
methodID = env->GetMethodID(clazz, "logMessage",
"(Ljava/lang/String;)V");
// Release the class reference
env->DeleteLocalRef(clazz);
}
// If method is found
if (NULL != methodID)
{
// Format the log message
char buffer[MAX_LOG_MESSAGE_LENGTH];
va_list ap;
va_start(ap, format);
vsnprintf(buffer, MAX_LOG_MESSAGE_LENGTH, format, ap);
va_end(ap);
Download at http://www.pin5i.com/
217 CHAPTER 8: POSIX Socket API: Connection-Oriented Communication
// Convert the buffer to a Java string
jstring message = env->NewStringUTF(buffer);
// If string is properly constructed
if (NULL != message)
{
// Log message
env->CallVoidMethod(obj, methodID, message);
// Release the message reference
env->DeleteLocalRef(message);
}
}
}
/**
* Throws a new exception using the given exception class
* and exception message.
*
* @param env JNIEnv interface.
* @param className class name.
* @param message exception message.
*/
static void ThrowException(
JNIEnv* env,
const char* className,
const char* message)
{
// Get the exception class
jclass clazz = env->FindClass(className);
// If exception class is found
if (NULL != clazz)
{
// Throw exception
env->ThrowNew(clazz, message);
// Release local class reference
env->DeleteLocalRef(clazz);
}
}
/**
* Throws a new exception using the given exception class
* and error message based on the error number.
*
* @param env JNIEnv interface.
* @param className class name.
* @param errnum error number.
*/
static void ThrowErrnoException(
JNIEnv* env,
const char* className,
int errnum)
{
char buffer[MAX_LOG_MESSAGE_LENGTH];
// Get message for the error number
if (-1 == strerror_r(errnum, buffer, MAX_LOG_MESSAGE_LENGTH))
{
strerror_r(errno, buffer, MAX_LOG_MESSAGE_LENGTH);
}
// Throw exception
ThrowException(env, className, buffer);

 

 

通过这通信的生命周期,和处理这排序和错误检查括号来自这应用程序。将修改者例子Echo应用程序来包含Tcp服务器和客户端activites为了占建立的连接和信息交换使用sockets。

Echo Server Activity布局

 使用Project Explorer视图,展开res目录。展开layout子目录,和创建一个新的布局文件叫做Activity_echo_server.xml.如下:

   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
Download at http://www.pin5i.com/
219 CHAPTER 8: POSIX Socket API: Connection-Oriented Communication
<EditText
android:id="@+id/port_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/port_edit"
android:inputType="number" >
<requestFocus />
</EditText>
<Button
android:id="@+id/start_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/start_server_button" />
</LinearLayout>
<ScrollView
android:id="@+id/log_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/log_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>

这个Echo Server提供了一个简单的用户接口来获得端口来绑定服务器和来呈现着状态更新来着这原生Tcp 服务区在它正在执行。

Echo Server Activity:

   使用创建EchoServerAcitivity.java在src目录下。

package com.apress.echo;
/**
* Echo server.
*
* @author Onur Cinar
*/

public class EchoServerActivity extends AbstractEchoActivity {
/**
* Constructor.
*/
public EchoServerActivity() {
super(R.layout.activity_echo_server);
}
protected void onStartButtonClicked() {
Integer port = getPort();
if (port != null) {
ServerTask serverTask = new ServerTask(port);
serverTask.start();
}
}
/**
* Starts the TCP server on the given port.
*
* @param port
* port number.
* @throws Exception
*/
private native void nativeStartTcpServer(int port) throws Exception;
/**
* Starts the UDP server on the given port.
*
* @param port
* port number.
* @throws Exception
*/
private native void nativeStartUdpServer(int port) throws Exception;
/**
* Server task.
*/
private class ServerTask extends AbstractEchoTask {
/** Port number. */
private final int port;
/**
* Constructor.
*
* @param port
* port number.
*/
public ServerTask(int port) {
this.port = port;
}
protected void onBackground() {
logMessage("Starting server.");
try {
nativeStartTcpServer(port);
} catch (Exception e) {
logMessage(e.getMessage());
}
logMessage("Server terminated.");
}
}
}

   实现原生TCP服务:

  使用Project Explorer,选择这EchoServerActivity,和产生C和C++头文件。打开Echo.cpp源文件。出入include语句,如下:

  #include "com_apress_echo_EchoServerActivity.h"

    创建一个Socket:socket

  一个socket通过一个叫做socket描述符的整形术来代表。Socket API函数,而不是这创建这socket本身,需要一个有效的socket描述符对于这个函数。一个socket函数被创建使用这socket函数。

   int socket(int domain,int type,int protocol);

  这个socket函数需要如下参数来创建一个新的socket:

  Domain指定这socketdomain,通信选择的协议族。在这写的期间,接下来的协议族被Android平台所支持。

  PF_LOCAL:Host-interanl通信协议。这个通信协议能够使用应用程序那运行在同样的设备来使用Socket APIs来相互通信。

  PF_INET:internet 版本4端口协议。这个端口使应用协议和正在这个网络运行的的应用程序相互通信。

  Type指定了通信的语义。接下的主要的socket类型被支持的:

       SOCKET_STREAM:流端口类型同基于连接的通信使用Tcp端口。

      SOCKET_DGRAM:数据报类型提供了无连接的通信使用UDP端口。

    Protocol指定了将要被使用的端口。对于大部分的端口协议族和类型,仅仅只用一种坑能的端口被使用。为了选择默认的端口,这个参数被设置为0.

    socket函数返回相关联的socket描述符;-1和错误errno的全局变量被设置到这恰当的error。

   NewTcpSocket帮助函数对于Echo.cpp原生模块

* @throws IOException
*/
static int NewTcpSocket(JNIEnv* env, jobject obj)
{
// Construct socket
LogMessage(env, obj, "Constructing a new TCP socket...");
int tcpSocket = socket(PF_INET, SOCK_STREAM, 0);
// Check if socket is properly constructed
if (-1 == tcpSocket)
{
// Throw an exception with error number
ThrowErrnoException(env, "java/io/IOException", errno);
}
return tcpSocket;
}

    这个帮助函数创建了一个新的TCP socket和失败是抛出一个java.lang.IOException异常。

  绑定这Socket到一个地址:bind

  当一个Socket被创建通过socket函数,它存在一个socket协议族空间没有一个端口地址分配给它。对于客户端能够指定和连接到这个端口,它需要首先绑定一个地址。一个socket能够绑定到一个地址使用bind函数。

   int bind(int socketDescriptor,const struct sockaddr* address,socklen_t addressLength);

   这绑定函数需要如下参数为了绑定着socket到一个地址:

   这socket描述符指定socket实例将绑定到这给定的地址。

  这地址指定了端地址,socket将会绑定的。

  这地址长度指定了端口地址结构的长度被传递给这个函数。

  取决于端口地址,一个不同特色的端口地址被使用。对于PF_INET端口协议,这socketaddr_in结构体被使用来指定和端口地址。这socketaddr_in结构体的定义如下:

    struct sockaddr_in {
sa_family_t sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
}

  如果这个端口被恰当的绑定,和bind函数将返回0;否则,它将返回-1和这errno全局变量到这恰当错误。

   使用这Editor视图,添加这BindSocketToPort帮助函数到Echo.cpp本地模块源文件如下:

    /**
* Binds socket to a port number.
*
* @param env JNIEnv interface.
* @param obj object instance.
* @param sd socket descriptor.
* @param port port number or zero for random port.
* @throws IOException
*/

static void BindSocketToPort(
JNIEnv* env,
jobject obj,
int sd,
unsigned short port)
{
struct sockaddr_in address;
// Address to bind socket
memset(&address, 0, sizeof(address));
address.sin_family = PF_INET;
// Bind to all addresses
address.sin_addr.s_addr = htonl(INADDR_ANY);
// Convert port to network byte order
address.sin_port = htons(port);
// Bind socket
LogMessage(env, obj, "Binding to port %hu.", port);
if (-1 == bind(sd, (struct sockaddr*) &address, sizeof(address)))
{
// Throw an exception with error number
ThrowErrnoException(env, "java/io/IOException", errno);
}
}

   如果端口号被设定为0在地址结构体中,这bind函数将分配第一个可能的端口号给这个socket。端口号可以被获得通过使用getsocketname函数。如下:

    /**
* Gets the port number socket is currently binded.
*
* @param env JNIEnv interface.
* @param obj object instance.
* @param sd socket descriptor.
* @return port number.
* @throws IOException
*/
static unsigned short GetSocketPort(
JNIEnv* env,
jobject obj,
int sd)
{
unsigned short port = 0;
Download at http://www.pin5i.com/
225 CHAPTER 8: POSIX Socket API: Connection-Oriented Communication
struct sockaddr_in address;
socklen_t addressLength = sizeof(address);
// Get the socket address
if (-1 == getsockname(sd,
(struct sockaddr*) &address,
&addressLength))
{
// Throw an exception with error number
ThrowErrnoException(env, "java/io/IOException", errno);
}
else
{
// Convert port to host byte order
port = ntohs(address.sin_port);
LogMessage(env, obj, "Binded to random port %hu.", port);
}
return port;
}

 

     你可能注意到,这个端口号并没有直接的传递到sockaddr_in结构体。代替的是,这htons函数被用来首先做转换。这是由于host和网络字节的排序的不同。

网络字节的排序:

    不同的机器架构使用不同的规则对于数据的排序在硬件水平。下面是著名的字节顺序:

    大端排序:先存储大端字节。

   小端排序:先存储最后有意义的字节。

带有不同字节排序的规则的机器不能直接交换数据。为了使用带有不同字节排序规则的机器相互通信通过网络,这internet端口定义了大端排序作为官方的网络字节排序转换对于数据的转换。

   正如Java虚拟机已经使用了大端字节排序,这第一次你正听说

字节序数据。Java应用程序并没有做任何转换对于数据当在网络上传输数据时。相比而言,对于原生的组件不能被执行在Java虚拟机上,他们使用的机器自己排序如下:

      ARM和x86机器架构使用小端字节排序。

      MIPS机器架构使用达到字节排序。

当通过网络通信,这原生的代码必须在机器字节排序和网络字节排序镜像转换。

这Socket库提供了一套转换函数来使原生的应用程序透明的操作字节顺序的转换。这些函数被定义通过这sys/endian.h头文件:

     #include<sys/endian.h>

  这接下转换函数被提供如下:

   htons函数转换一个无符号short从host机器字节顺序到网络字节顺序。

   ntohs函数和htons相反,通过转换一个无符号的short类型数据从网络到host机器的字节顺序。

   htonl函数转换一个无符号的整形术从host机器字节顺序到网络字节顺序。

   ntohl函数和htonl函数相反。

  监听到来的连接:listen

   通过listen函数监听一个socket:

  int listen(int socketDescriptor,int backlog);

   这个监听函数需要如下的参数被提供来开始监听到来的连接:

       这socket描述符指定了socket实例这应用程序想要开始监听到来的连接。

      这backlog指定这队列的长度来保存着pending到来的连接。如果应用程序时繁忙的服务一个客户端,其他到来的连接排队到一定数量的pengding有backlog。当backlog是满时,连接被拒绝。

如果函数成功返回0,否则-1;

/**
* Listens on given socket with the given backlog for
* pending connections. When the backlog is full, the
* new connections will be rejected.
*
* @param env JNIEnv interface.
* @param obj object instance.
* @param sd socket descriptor.
* @param backlog backlog size.
* @throws IOException
*/
static void ListenOnSocket(
JNIEnv* env,
jobject obj,
int sd,
int backlog)
{
// Listen on socket with the given backlog
LogMessage(env, obj,
"Listening on socket with a backlog of %d pending connections.",
backlog);
if (-1 == listen(sd, backlog))
{
// Throw an exception with error number
ThrowErrnoException(env, "java/io/IOException", errno);
}
}

接收到来的连接:accept

  这accept函数被明确的用来放置到来的连接从监听队列到接收它。

  int accept(int socketDescriptor,struct sockeaddr* address,socklen_t* addressLength);

 这个accept函数时一个阻塞函数。如果没有阻塞到来的连接请求在监听队列,它放置着调用线程到一个阻塞的状态知道一个新到来的连接到达。这accept函数需要的参数:

    这socket 描述符指定了这socket的实例,应用程序想要接收一个pending的到来的连接。

     这地址的长度指针提供了一个地址结构,填充了要连接的客户端的端口地址。如果信息不被应用程序所需要,它被设置为null。

    这地址的长度指针同了连接客户端端口地址的长度要分配的内存空间。如果信息不被需要则设置为NULL。

accept请求成功,这函数返回客户端描述符,否则为-1和errno全局变量被设置。

    LogAddress帮助函数到原生模块源文件,如下:

   /**
* Logs the IP address and the port number from the
* given address.
*
* @param env JNIEnv interface.
* @param obj object instance.
* @param message message text.
* @param address adress instance.
* @throws IOException
*/
static void LogAddress(
JNIEnv* env,
jobject obj,
const char* message,
const struct sockaddr_in* address)
{
char ip[INET_ADDRSTRLEN];
// Convert the IP address to string
if (NULL == inet_ntop(PF_INET,
&(address->sin_addr),
ip,
INET_ADDRSTRLEN))
Download at http://www.pin5i.com/
229 CHAPTER 8: POSIX Socket API: Connection-Oriented Communication 
{
// Throw an exception with error number
ThrowErrnoException(env, "java/io/IOException", errno);
}
else
{
// Convert port to host byte order
unsigned short port = ntohs(address->sin_port);
// Log address
LogMessage(env, obj, "%s %s:%hu.", message, ip, port);
}
}





static int AcceptOnSocket(
JNIEnv* env,
jobject obj,
int sd)
{
struct sockaddr_in address;
socklen_t addressLength = sizeof(address);
// Blocks and waits for an incoming client connection
// and accepts it
LogMessage(env, obj, "Waiting for a client connection...");
int clientSocket = accept(sd,
(struct sockaddr*) &address,
&addressLength);
// If client socket is not valid
if (-1 == clientSocket)
Download at http://www.pin5i.com/
230 CHAPTER 8: POSIX Socket API: Connection-Oriented Communication 
{
// Throw an exception with error number
ThrowErrnoException(env, "java/io/IOException", errno);
}
else
{
// Log address
LogAddress(env, obj, "Client connection from ", &address);
}
return clientSocket;
}


recv函数是一个阻塞函数。如果没有数据从给定的socket被接收到,它将放着调用进程到阻塞状态直到数据可以使用。这recv函数需要的参数如下:

   这socket描述符指定了socket实例,应用程序想要接收数据的socket实例。

    这buffer指针是将要填充接收到数据的内存地址。

    Flages中指定了可惜标记。

如果recv函数成功,它将返回接收到数据的字节数目;否则,它将返回-1和errno全局变量被设置恰当的错误。如果函数返回0,它将指示socket是断开连接的。使用如下:

  static ssize_t ReceiveFromSocket(
JNIEnv* env,
jobject obj,
int sd,
char* buffer,
size_t bufferSize)
{
// Block and receive data from the socket into the buffer
LogMessage(env, obj, "Receiving from the socket...");
ssize_t recvSize = recv(sd, buffer, bufferSize - 1, 0);
// If receive is failed
if (-1 == recvSize)
{
// Throw an exception with error number
ThrowErrnoException(env, "java/io/IOException", errno);
}
else
{
// NULL terminate the buffer to make it a string
buffer[recvSize] = NULL;
// If data is received
if (recvSize > 0)
{
LogMessage(env, obj, "Received %d bytes: %s", 
recvSize, buffer);
}
else
{
LogMessage(env, obj, "Client disconnected.");
}
}
return recvSize;
}



发送数据到Socket:send

发送数据到socket通过发送函数:

     ssize_t send(int socketDescriptor,void* buffer,size_t bufferLeng,int flags);

像recv函数,这发送函数也是个阻塞函数。如果这socket是繁忙的发送数据,它放置调用进程到一个阻塞状态直到对于传输的数据准备好。这发送函数需要接下的参数被提供为了及时一个pending到来的连接:

     这socket描述符指定了应用程序想要发送数据给的socket实例

     这buffer指针指向了要发送数据的内存地址。

    这buffer长度指定了这buffer的大小。这send函数仅仅传输者buffer到这个长度和返回。

    Flages指定额外的发送标记。

    send函数返回传输的的字节数据如果成功,否则-1和制定了恰当错误的全局变量errno。像recvSendToSocket帮助函数,如下:

    static ssize_t SendToSocket(
JNIEnv* env,
jobject obj,
int sd,
const char* buffer,
size_t bufferSize)
{
// Send data buffer to the socket
LogMessage(env, obj, "Sending to the socket...");
ssize_t sentSize = send(sd, buffer, bufferSize, 0);
Download at http://www.pin5i.com/
233 CHAPTER 8: POSIX Socket API: Connection-Oriented Communication 
// If send is failed
if (-1 == sentSize)
{
// Throw an exception with error number
ThrowErrnoException(env, "java/io/IOException", errno);
}
else
{
if (sentSize > 0)
{
LogMessage(env, obj, "Sent %d bytes: %s", sentSize, buffer);
}
else
{
LogMessage(env, obj, "Client disconnected.");
}
}
return sentSize;
}


     

 

 

 

 
socket实现简单的echo应答服务器和客户端 #include #include #include #include #include #include #include static const int MAXPENDING = 5; static const int BUFSIZE = 1024; void HandleTCPClient(int clntSocket); void DieWithUserMessag 阅读详情

相关推荐

Android NDK tcp例子

Android NDK tcp例子,客户端app和服务端app通过ndk进行socket通信

17.Socket双向通讯(ECHO程序)

服务端 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; impo

Yang_Ke_Di的博客 1260

达梦数据库JDBC连接池断开自动重连设置

一、场景 在网络状况不是非常良好,经常会出现暂时性的拥塞或者断开的情况,而且当我们重启数据库时也会发生类似的情况。所以需要配置中间件的连接池来实现连接测试以及自动重连,通过重新配置连接池,成功解决了这个问题。下面会给出一份数据源配置参数详单和一份推荐的数据源配置项。 二、连接池配置参数 1. initialSize:连接池启动时创建的初始化连接数量 2. maxActive:连接池中可同时连接的最大的连接数 3. maxIdle:连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负

lilv1989的博客 7235

Laravel/Lumen 中使用 Echo + Socket.IO-Client 实现网页即时通讯广播

Web 端客户端必须使用^2.0版本,不可使用^3.0或^4.0(Client Demo 中已说明),除非中依赖的socket.io服务版本变更。所以配置中选项是无效的。部分配置项可写在项目根目录的.env启动 WebSocket 服务端,在项目根目录运行;编写广播事件,参考;通过;启动 Web 网页并连接到服务端,连接端口为中的port配置项;使用命令启动队列监听以执行消费,根据示例文件应当在项目根目录运行队列提示消费DONE完成后,事件中方法的返回值将被传送至 Web 端,至此流程结束。

Right! I'm Max Sky. 2136

Python连接StarRocks全流程实践: SQL文件调用与Pandas混合优化

通过这种分阶段混合计算, 既能发挥StarRocks处理海量数据的性能优势, 又能保留Pandas在内存计算中的灵活性, 实现效率与功能的完美平衡.结合SQL的高效聚合与Pandas的灵活计算, 实现查询和数据处理的深度融合.该库基于SQLAlchemy 2.x开发, 仅支持Python 3.x环境.对大批量数据的写入, 建议进行分块. 分块写入较单条插入速度会有显著提升.这样可以避免python代码的查询与SQL耦合, 支持版本化管理.将DDL, DML分离为独立文件, 例如。: 调整连接复用参数。

t.y.Tang的博客 2780

别再乱短接了!OEC/OEC-turbo刷机救砖,用RKDevTool避开‘下载boot失败’的保姆级教程

本文提供OEC/OEC-turbo刷机救砖的终极指南,重点介绍使用RKDevTool避开‘下载boot失败’的详细步骤。从Loader模式的优势到硬件准备细节,再到分阶段刷机方案,帮助用户高效完成设备恢复,避免反复短接和常见误区。

weixin_29280657的博客 1103

ndk中使用native Socket

socket进程通信命名方式有两种。一是普通的命名,socket会根据此命名创建一个同名的socket文件,客户端连接的时候通过读取该socket文件连接到socket服务端。这种方式的弊端是服务端必须对socket文件的路径具备写权限,客户端必须知道socket文件路径,且必须对该路径有读权限。 另外一种命名方式是抽象命名空间,这种方式不需要创建socket文件,只需要命名一个全局名字,即

hb707934728的博客 2433

【汽车ECU标定技术解析】DCM文件与A2L、HEX的协同工作机制

本文深入解析了汽车ECU标定中DCM、A2L与HEX三大核心文件的协同工作机制。A2L文件作为定义标定变量地址与规则的“图纸”,DCM文件承载工程师调试后的具体标定数据,最终通过A2L的地址映射,将DCM数据固化生成可刷入ECU的HEX文件,形成完整的标定数据流转闭环。

weixin_29214559的博客 437

linux socke编程实例:一个简单的echo服务器程序

    也许是第一次真正使用linux操作系统,忽然对丢弃已久的C产生了很大的兴趣,最近想学点linux的知识,在linux的世界里面,接触得最多的还是C,故有感写一下linux的socket程序。    也许很多朋友会像我一样,这样的程序在Java写得太多,以至对Socket的通信细节还不曾忘怀。由于未有linux下的编程经验,在写程序过程中碰到很多不懂的东西,经过google一翻后,终于把一些

海枫的专栏 1万+

PySpark机器学习生产化陷阱:跨节点依赖问题的7种解决方案

隐式依赖陷阱使用ldd解决方案:在基础镜像中预装和路径冲突终极解法依赖树瘦身技巧用conda-tree可减少40%环境体积PySpark机器学习生产化的核心矛盾在于分布式环境的确定性与灵活性不可兼得。轻量级方案(1-3)牺牲一致性换取灵活性重量级方案(4-6)牺牲灵活性换取确定性混合方案(7)针对特殊场景补充正如某AI平台架构师所言:“环境一致性不是技术问题,而是工程纪律问题选择适合团队当前阶段的方案,建立严格的依赖管理流程,才能让PySpark真正扛起生产环境的大旗。

datacanvas2426的博客 911

TC8:IPv4_HEADER_01-04

IPv4_HEADER_01: Ensure that the DUT generates an IPv4 Packet with a Total Length greater than or equal to 20 目的 确保DUT生成的IPv4报文的IP头部中的Total Length字段值大于等于20 IPv4协议头部中的Total Length字段表示整个IP数据包的长度,包括IP Header和payload之和,IP首部的长度最少就有20个字节,所以Total Length值肯定大于等于20

jasonj333 3961

Socket echo server

因为他们的第一个字段是一样的,所以可以用 sockaddr_in和sockaddr_un强转成sockaddr结构,并提取第一个字段判断是AF_INET还是AF_UNIX选择强转成sockaddr_in还是sockaddr_un结构,也就是C语言版的继承和多态。知名端口号比如:HTTP(80),HTTPS(443),DNS(53)。2. 当server启动的时候,就需要accpet获取连接,也就是有连接来了,获取到的连接分配一个文件描述符来进行读写,所以要起多线程/多进程,不然会阻塞后续的accpet。

CD200309的博客 698

前程无忧Python岗位数据采集:基于API直连的高效招聘信息爬取实战

本文介绍了一个基于Python requests库的前程无忧招聘数据采集系统。项目通过分析API接口结构,配置完整的请求头和身份验证参数,实现了高效稳定的数据采集。系统支持多页数据批量获取,包含工作名称、薪资范围等关键字段的结构化解析,并将结果存储为Excel文件。技术实现涉及API分析、身份验证、请求头配置、数据清洗等关键步骤,同时强调遵守法律和道德规范。该系统可为求职者、HR和市场分析师提供有价值的行业数据支持,适用于市场分析、职业规划等场景。

那些看似不起波澜的日复一日,会在某天让你看到坚持的意义 1552

【Linux网络】Socket编程实战,基于UDP协议的Echo Server

本文详细介绍了基于UDP协议的Socket编程实现EchoServer服务。主要内容包括: 服务器端实现分为初始化阶段(创建套接字、绑定信息)和运行阶段(接收并回显消息) 详细讲解了socket()、bind()、recvfrom()、sendto()等关键系统调用的使用 完整实现了UDP服务器类,包含日志模块和互斥锁封装 客户端实现注意事项,包括端口自动绑定机制 优化方案:服务器使用INADDR_ANY绑定任意地址,增加回调函数处理消息 提供了完整的代码实现,包括服务器和客户端的通信示例 该实现展示了基本

记录学习与成长 5037

第4章-07-将WebDriver获取的Cookie传递给Requests

在使用Selenium WebDriver获取了浏览器的Cookies之后,你可以将这些Cookies传递给requests库,以便在后续的HTTP请求中使用这些Cookies。这样做可以让你模拟浏览器会话,使得请求看起来像是从之前使用Selenium WebDriver控制的浏览器发出的。

黑夜开发者的博客 692

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【Linux网络】Socket编程:UDP网络编程实现Echo Server

在上篇文章中,我们已经铺垫了一些前置知识,这一篇文章我们就来实现UDP网络编程,实现一个Echo Server,就是客户端给服务端发送一条消息,服务端接收后,再转发给客户端,回显出来。

2402_82670467的博客 3417

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

基于 Socket 和多线程的简单 Echo 服务器实现

创建 TCP 服务器 Socket(绑定本地 2000 端口)。监听客户端连接请求。每当有客户端连接,就创建一个线程专门负责和该客户端通信。通信逻辑:客户端发来什么消息,服务器就原样返回什么。也就是说,这是一个最简单的多线程 TCP Echo 服务器。这段代码实现了一个最小可用的多线程 TCP Echo 服务器,主要用来理解:Socket 的创建与绑定。accept 的作用(连接建立)。recv/send 的通信逻辑。pthread 的多线程处理。

qq_64148519的博客 1073

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

icmp echo socket发包学习

linux icmp echo socket发包处理。

qq_38604769的博客 777

【Linux网络】Socket编程TCP-实现Echo Server(上)

本篇将基于Socket编程TCP实现一个Echo Server。这个EchoServer的功能和中实现的是一样的。1.预备工作首先我们要创建如下几个文件。一般来说,为了不让服务器能被拷贝,我们可以设计成单例模式,或者把服务器的赋值以及拷贝构造设为私有或禁用,单例模式之前实现过这里就不选择单例模式了,我们把复制和拷贝构造私有的话那如果UDP也想自己不被拷贝呢?这里介绍另一种方式,首先在Common.hpp里实现一个NoCope的类。然后让服务器的类继承NoCope类。

2402_82757055的博客 1378

socket实现一个简单的echo服务

服务端的实现: public class EchoServer{ //创建一个serverSocket private final ServerSocket serverSocket; //创建一个构造器 传入端口 public EchoServer(int port) throws IOException{ ...

华为云官方博客 2434

【网络】TCP与UDP协议使用指南,Socket编程实现Echo服务

本文介绍了TCP和UDP协议的核心特点及网络编程基础。主要内容包括: TCP与UDP协议对比 TCP是面向连接、可靠传输的字节流协议 UDP是无连接、不可靠传输的数据报协议 网络字节序规范 网络传输统一使用大端模式 提供htonl/htons等函数进行主机序和网络序转换 Socket编程核心接口 创建socket和绑定IP端口的基本方法 UDP使用recvfrom/sendto进行数据收发 TCP通过listen/accept/connect建立连接 连接建立后可使用read/write通信

记录我一步步的学习历程,期待无限进步,向星举目! 2443

网络6 -- udp_socket 实现 echo服务器

使用 func() 函数回调,从main()函数中获取数据。创建套接字时,我们要将字符型的port和ip转化为网络序列。

weixin_73964834的博客 1721

python socket tcp本机echo通信

使用了socket模块,分为sever和client两部分。 环境:python3.7,pycharm sever主要进程:1.SOCKET.SOCKET 2.bind 绑定 3.listen 4.accept 5.send&recv 6.close client主要进程: 1.socket.socket 2.connect()连接至sever端 3.send&received 4...

chitubuchitu的博客 699

echo socket java,java socket 多线程echo服务器

在文章java socket 单线程echo服务器中实现的echo服务器有一个问题,就是Server只能接受一个Client请求,当第一个Client连接后就占据了这个位置,后续Client不能再继续连接。在实际的网络环境里,同一时间只对一个用户服务是不可行的。一个优秀的网络服务程序除了能处理用户的输入信息,还必须能够同时响应多个客户端的连接请求。所以需要做些改动,当Server每接受到一个Cl...

weixin_27945229的博客 273

socket服务实例:TCP(面向流的socket)实现ECHO服务器与客户端

所谓的ECHO服务就是在屏幕打印相关的参数,相关的应用过程如下: 服务器逻辑 1.服务器启动之后创建服务器socket,进行相应的设置后始终调用accept(2)等待客户端的连入,客户端 正常连入之后创建一个子进程作为业务进程,对客户端进行服务,父进程 始终作为监听进程等待下一个客户端的连入; 2.其中为了防止僵尸进程的出现,服务器需要有处理子进程退出的功能,简便起见,程序中直接安装一个信号处理程序,用于处理SIGCHLD信号,这个过程完全异步,没有体现在流程图内。 如图为程序流程图 但是该服务器的.

LCY133的博客 3535

用python实现一个socket echo程序 && tcp socket的几个关闭状态

用python实现一个socket echo程序 && tcp socket的几个关闭状态 用python实现一个socket echo程序 && tcp socket的几个关闭状态 - 真实的活 - 博客园用python实现一个s...

125
上一篇: POSIX线程的同步
下一篇: Socket UDP无连接通信
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值