监听socket初始化

主要在俩块内容中用到socket的初始化部分,第一块是在ngx_http_core_srv函数中,在最后设置默认的监听套接口时有把监听socket添加进去,第二块是在ngx_http_block的最后,把配置文件的socket添加进去

1.结构信息:
一个port可以对应多个addr,可有多个server监听同一个addr:port,所以在addr中比较重要的几个成员如下:
default_server,该端口默认的server
servers:所有在该端口下监听的server
hash:server name为key,ngx_http_core_srv_conf_t为value的哈希表
2.解析配置文件,获取监听socket信息
用于设置监听socket的指令有俩个,server_name和listen,前者用于设置每个server的虚拟主机名,后者用于设置socket信息,
1》前者对应的函数为ngx_http_core_server_name,它的作用是将server_name指定的虚拟主机名字添加到ngx_http_core_srv_conf_t中的server_names数组中,其实他就相当于一个域名的存在
ps:server_name的配置举例:
server_name jb51.net;比如http://jb51.net的请求就会转发到该主机
server_name jb51.net www.jb51.net;http://www.jb51.net
server_name *.jb51.net;设置该主机处理所有来自jb51.net的子域名,比如www.jb51.net,blog.jb51.net等
2》socket对应得函数是ngx_http_core_listen函数
该函数负责解析listen指令配置项的socket配置信息,并且保存这些值,在函数的最后调用ngx_http_add_listen函数添加监听socket信息
cscf->listen=1
//一旦采用了listen指令就代表要使用相应的配置信息,如果他为0的话,那么就要在Ngx_http_core_srv函数中配置默认的监听信息

value = cf->args->elts;

ngx_memzero(&u, sizeof(ngx_url_t));

u.url = value[1];
u.listen = 1;
u.default_port = 80;

if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
if (u.err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
“%s in \”%V\” of the \”listen\” directive”,
u.err, &u.url);
}

return NGX_CONF_ERROR;  

}
//解析listen指令的url,ip和端口号信息
初始化ngx_http_listen_opt_t结构体,它里面存储着一些基本的socket选项,比如常见的recbuf,sndbuf,backlog,而后调用ngx_sock_ntop把二进制的地址转化为文本格式存入ngx_http_listen_opt_t结构体。
最后调用ngx_http_add_listen函数添加监听socket信息
ngx_http_add_listen的实现:
a.如果ports为NULL(不为空,就是说已经解析了一个listern),则为ngx_http_core_module的ngx_http_core_main_conf_t.ports分配ngx_http_conf_port
b.通过lsopt获取端口信息赋值给变量p
c.这段代码是遍历ports数组,查看新添加的端口信息是否已经存在,如果该端口信息存在则调用ngx_http_add_addresses函数在对应的端口结构上添加地址信息。否则,在prots数组中添加一个元素,并初始化,
d.查找port->addrs数组中是否已经添加了该ip,如果是,则调用ngx_http_add_server把对应得ngx_http_core_srv_conf_t配置添加到ngx_http_conf_addr_t的servers数组中。
- 若没找到该IP,调用ngx_http_add_address把IP初始化到ngx_http_conf_addr_t结构,添加到port的addrs数组中。
并且设置default_server,往往是第一个监听该addr:port的是它的默认server,最后同样调用nginx_http_add_server添加server块的配置信息
3》函数ngx_http_block函数中调用ngx_http_optimize_servers函数完成ngx_listening_t初始化,下面看一下这个函数的实现。
a.先调用ngx_http_server_names初始化ngx_http_conf_addr_t中的三个哈希表
b.调用ngx_http_init_listening初始化ngx_cycle_t中的ngx_listening_t结构体
b.1调用ngx_http_add_listening函数往ngx_cycle_t的listenings数组中添加监听socket
ngx_http_add_listening函数的实现:
b.11:ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen);
//创建ngx_listening_t结构体,并且把它添加到listening数组中,并且设置该ngx_listening_t结构体中的一些主要的成员信息
b.12:// 设置监听socket的handler,在监听到新的连接时调用,即ngx_event_accept中。
ls->handler = ngx_http_init_connection;
b.2:调用ngx_http_add_addrs函数初始化ngx_listening_t中的servers成员,在处理请求时进行匹配并且赋值给request成员

4》接下来会在ngx_init_cycle函数中调用ngx_open_listening_sockets和ngx_configure_listening_sockets完成监听套接口的打开和配置
5》接下来就会在ngx_event_process_init函数(ngx_event_core_moduel的process_init回调函数,在创建完worker进程后调用)中将这些监听socket添加到事件循环中

综上所述,其实主要的流程就是读取配置文件,设置好端口,地址,server这三个数据的关系,而后打开套接口就可以

<think>好的,用户想知道在Socket初始化时如何传输数据,并需要示例代码。首先,我需要明确“Socket初始化”具体指哪个阶段。通常,Socket初始化包括创建套接字、配置地址结构、绑定、监听(服务端)或连接(客户端)等步骤。用户可能想问的是在建立连接后如何传输数据,或者是在连接建立过程中传递初始数据。 根据常见的Socket编程流程,传输数据一般是在连接建立之后进行的。例如,在TCP中,客户端通过connect()连接到服务端后,双方使用send()和recv()函数交换数据。但用户提到的是“初始化时传递数据”,这可能意味着在连接建立的同时发送数据,比如在握手阶段携带信息。不过,标准的Socket API在连接阶段(如connect()或accept())并不直接支持附带数据,数据传输需要等到连接成功后才能进行。 接下来,我需要考虑不同编程语言的实现差异。用户提供的引用中提到了Python、Java和C/C++的示例,但用户的问题可能不限定语言。因此,需要给出通用的步骤,并附上不同语言的示例代码。 首先,解释Socket初始化的基本步骤:创建Socket配置地址、连接(客户端)或绑定和监听(服务端)。数据传输发生在连接建立之后,通过send和recv方法。然后,可能需要说明在初始化阶段无法直接传输数据,必须等到连接成功。 然后,提供示例代码。比如,在Python中,客户端连接后立即发送数据,服务端接收。同样地,展示Java和C/C++的实现。需要注意的是,不同语言在Socket API的使用上有所不同,比如Java使用Socket和ServerSocket类,而C/C++使用系统调用如socket(), connect(), send(), recv()等。 另外,需要检查是否有引用中的内容可以支持回答。引用[3]提到了C/C++创建Socket的示例,引用[2]讨论了服务端管理客户端连接的问题,引用[1]则涉及WebSocket的握手过程。虽然用户的问题是关于普通Socket,但可以指出WebSocket在握手时通过HTTP头传递数据,但这是不同的协议,可能超出用户当前问题的范围。不过,可以简要提及作为扩展。 最后,生成相关问题,帮助用户深入理解Socket数据传输的其他方面,比如协议选择、数据序列化、错误处理等。</think>在Socket编程中,数据传输发生在连接建立后的阶段。以下是初始化Socket并传输数据的通用步骤和示例代码: --- ### 一、数据传输基本流程 1. **创建Socket**:指定协议类型(如TCP/IP) 2. **建立连接** - 客户端:`connect()`到服务端 - 服务端:`bind()`+`listen()`+`accept()` 3. **发送/接收数据** - 客户端/服务端:通过`send()`和`recv()`传输数据[^3] --- ### 二、代码示例(Python) #### 客户端 ```python import socket # 1. 初始化Socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2. 建立连接 client_socket.connect(('127.0.0.1', 8080)) # 3. 传输数据 client_socket.send(b"Hello Server! Initial data from client") response = client_socket.recv(1024) print("Received:", response.decode()) ``` #### 服务端 ```python import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('127.0.0.1', 8080)) server_socket.listen(1) conn, addr = server_socket.accept() data = conn.recv(1024) print("Client says:", data.decode()) conn.send(b"Server received your initial data") ``` --- ### 三、Java示例(带初始数据传输) ```java // 客户端 Socket clientSocket = new Socket("localhost", 8080); OutputStream out = clientSocket.getOutputStream(); out.write("Initial message".getBytes()); // 服务端 ServerSocket serverSocket = new ServerSocket(8080); Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println("Received: " + new String(buffer, 0, len)); ``` --- ### 四、关键技术点 1. **协议选择**: - `SOCK_STREAM`表示TCP(可靠传输) - `SOCK_DGRAM`表示UDP(无连接) 2. **数据序列化**:传输二进制数据时需处理编码(如JSON/Protobuf) 3. **错误处理**:需捕获`ConnectionRefusedError`等异常 --- ### 五、WebSocket的特殊性 在WebSocket协议中,**初始握手通过HTTP头传递数据**(如认证信息),成功后切换为帧格式通信[^1]。这与传统Socket的直接传输不同。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值