最后更新:2021-11-22 09:00:18 手机定位技术交流文章
这是一系列关于如何利用各种无障碍界面为Linux建立网络应用程序的文章中的第一篇。 Linux与其他基于Unix的操作系统一样,能够使用TCP/IP作为本地网络传输协议。 在这个系列中,我们假设你已经熟悉Linux的C写作和Linux的一些系统知识,例如信号、叉子等等。
提供文章是利用 BSD 界面创建网络应用程序的基本导言。 在下面的一篇文章中,我们将处理与Deamon 进程建立(联网)有关的困难。 今后,我们还将使用远程进程电话(RPCs)和生产CORBA/扭曲的物品。
一、TCP/IP 启动投资
这个小组是特别为在不可靠的网络上互动而建立的。 TCP/IP提供两个主要运作模式 -- -- 可靠的连接传输(意指TCP)和不可靠的非连接传输(UDP)。
TCP 提供一条连续、可靠、双向(双向)双向(双向)字节流,其基础是高级协议的透明中继功能。 TCP 将您的信息分离成一份数据报告(不大于64kb),并保证所有数据按向目的地的顺序准确记录。 由于连接以连接为基础,在一个网络实体与另一个网络实体之间通信之前必须建立虚拟连接。
每个程序必须有一个独立的地址才能相互交流,无论它们是否在同一台计算机上(通过回回路链接),还是在一个单独的主机上。
TCP/IP地址由两部分组成:识别系统IP地址和识别机器上具体软件的港口地址。
地址可以使用doted-qud (例如) 格式。 符号或主机名( 例如, 我很抱歉, csdn. I don't know what you're talking, but I don't know what you're talking. 系统可以使用 /etc/hosts/ hosts 或 DNS 域名服务( 如果有的话) 将主机名转换为点( ww.dotted- qud) 。 (互联网协议地址)
端口将从1.1开始,以IPP0RT_Reserved(in/usr/including/netinet/in)结束。h中所述的短语一般在1024之间,保留用于系统使用(即必须建立网络服务作为根来约束港口的这一部分)。
大多数最简单的网络程序都使用客户-服务器范式。 服务程序等待客户程序连接他。 连接建立后, 服务器代表客户执行指定任务, 通常中断连接 。
二. 使用 BSD 接口集进行通信。
BSD接口是最常用的TCP/IP编程方法,通过它,网络端点(IP地址和端口地址)以接口(套口)的形式出现。
收集IPC(进程间通信)能力的接口(在4.2BSD中引入),旨在使网络程序设计独立于不同的底部通信设施(在4.2BSD中引入),从而使得网络程序设计独立于不同的底部通信设施。
1. 创建服务器软件。
要使用 BSD 接口创建一个服务器应用程序,您必须首先做以下工作:
(1) 使用套接字 () 方法, 创建接口集合 。
(2) 使用约束()方法,约束地址(IP地址和端口地址),这一步骤可探测服务器的位置,并为客户提供如何到达服务器的概念。
(3) 使用 listm() 听(听) 方法在(听) 端口使用 listm() 听(听) 方法提出新的连接请求。
(4) 接受()方法接受一种新的联系。
通常需要一些时间才能维持代表客户的要求。在处理单一请求时,新请求的接收和处理也应迅速。最受欢迎的方法是服务器用叉子功能克隆自己的进程以获得新的连接。
以下示例展示了如何使用 C 创建服务器:
/*
* Simple "Hello, World!" server
* Ivan Griffin (ivan.griffin@ul.ie)
*/
/* Hellwolf Misty translated */
#include /* */
#include /* exit() */
#include /* memset(), memcpy() */
#include /* uname() */
#include
#include /* socket(), bind(),
listen(), accept() */
#include
#include
#include
#include /* fork(), write(), close() */
/*
* constants
*/
const char MESSAGE[] = "Hello, World!n";
const int BACK_LOG = 5;
/*
* 程序要求有一个命令行参数:要绑定的端口号。
*/
int main(int argc, char *argv[])
{
int serverSocket = 0,
on = 0,
port = 0,
status = 0,
childPid = 0;
struct hostent *hostPtr = NULL;
char hostname[80] = "";
struct sockaddr_in serverName = { 0 };
if (2 != argc)
{
fprintf(stderr, "Usage: %s n",
argv[0]);
exit(1);
}
port = atoi(argv[1]);
/ *
* 包含三个参数的系统调用 : 套接字 () 、 套接字_ id, 和套接字_ id_ id_ id_ id
* 参数域指通信域,例如PF_UNIX(UNIX字段)、PF_INET(IPv4字段),
* PF_INET6(IPv6)等。
2型是指最常见的通信形式,如SOCK_STREAM(一种可靠的连接方法)。
* 例如,TCP, SOCK_DGRAM(一种不可信的连接方法,例如UDP)。
*3,协议的论据定义了要使用的协议。这是相同的交易。
* 家庭(议定书家庭)(或属地)是指一组议定书。
* 参数,但一般只有一个,例如IPPROTO_TCP等TCP参数。
* UDP可用于IPPROTO_UDP,无需明确规定。
* 这两个参数都使用了缺省协议。
*/
serverSocket = socket(PF_INET, SOCK_STREAM,
IPPROTO_TCP);
if (-1 == serverSocket)
{
perror("socket()");
exit(1);
}
/*
在建立一套接口后,可以使用一套接口选项(口袋选项)改变工作程序。
*/
/*
* 配置 SO_REUSEADD 选项,在不必等待的情况下重新使用旧地址(IP加端口号)。
* 注意:如果套接字将Linux的端口捆绑起来,套接字一般关闭或应用程序结束。
* 港口长期保持开放,随后的程序(或重新启动的原始应用程序)无法约束港口。
*
* 以下呼吁目前正在进行中:SOL_SOCKET代表SOCKET层的行动。
*/
on = 1;
status = setsockopt(serverSocket, SOL_SOCKET,
SO_REUSEADDR,
(const char *) &on, sizeof(on));
if (-1 == status)
{
perror("setsockopt(...,SO_REUSEADDR,...)");
}
* 关闭延误(延迟)对确保连接丢失后所有数据都可用至关重要。
* 已转移, 因此必须启用 SO_ Linger 选项 。
* h:/usr/including/linux/socket中界定的内置结构。
* struct linger
* {
* int l_onoff; /* Linger active */
* int l_linger; /* How long to linger */
* };
* 如果 l_ onoff 是 0, 延迟关闭功能将被禁用。 如果超过 0, 设置的接口可能会晚点关闭 。
* L_linger 字段显示关闭延迟的时间长度。
*/
{
struct linger linger = { 0 };
linger.l_onoff = 1;
linger.l_linger = 30;
status = setsockopt(serverSocket,
SOL_SOCKET, SO_LINGER,
(const char *) &linger,
sizeof(linger));
if (-1 == status)
{
perror("setsockopt(...,SO_LINGER,...)");
}
}
/*
* find out who I am
*/
status = gethostname(hostname,
sizeof(hostname));
if (-1 == status)
{
perror("gethostname()");
exit(1);
}
hostPtr = gethostbyname(hostname);
if (NULL == hostPtr)
{
perror("gethostbyname()");
exit(1);
}
(void) memset(&serverName, 0,
sizeof(serverName));
(void) memcpy(&serverName.sin_addr,
hostPtr->h_addr,
hostPtr->h_length);
/*
*h_addr是h_addr_list[0]的同义词。
* 地址组称为 h_addr_list。
* IP地址的长度由长度4(字节)表示。
*/
/*
* 为了将服务器与其所有IP地址连接起来,
* 将前一行的代码替换为以下代码。
* serverName.sin_addr.s_addr=htonl(INADDR_ANY);
*/
serverName.sin_family = AF_INET;
* (主字节、主字节) htons: h
*至 n(网络和网络字节顺序)
*s(短期形式)
*/
serverName.sin_port = htons(port);
/ * 地址(在此示例中,服务器套件)形成后
它应该和我们得到的界面列表联系起来。
*/
status = bind(serverSocket,
(struct sockaddr *) &serverName,
sizeof(serverName));
if (-1 == status)
{
perror("bind()");
exit(1);
}
* 为收听新连接,现在有一套接口可供使用。
* 有待处理的链接窃听队列(监听传输队列)已由回声系统指定。
当新连接到来, 队列满后, 客户端的连接被错误拒绝 。
* (这是多斯拒绝服役攻击的基础。 )
*/
status = listen(serverSocket, BACK_LOG);
if (-1 == status)
{
perror("listen()");
exit(1);
}
* 接口的收集工作现已准备就绪,可以接收和服务各种请求。
* 这是实现此目标的循环方法的一个例子。
* 服务器可以通过指指手指和要求登录进入其客户的地址,进入客户的地址。
* 任务。
for (;;)
{
struct sockaddr_in clientName = { 0 };
int slaveSocket, clientLength =
sizeof(clientName);
(void) memset(&clientName, 0,
sizeof(clientName));
slaveSocket = accept(serverSocket,
(struct sockaddr *) &clientName,
&clientLength);
if (-1 == slaveSocket)
{
perror("accept()");
exit(1);
}
childPid = fork();
switch (childPid)
{
case -1: /* ERROR */
perror("fork()");
exit(1);
case 0: /* child process */
close(serverSocket);
if (-1 == getpeername(slaveSocket,
(struct sockaddr *) &clientName,
&clientLength))
{
perror("getpeername()");
}
else
{
printf("Connection request from %sn",
inet_ntoa(clientName.sin_addr));
}
/*
* Server application specific code
* goes here, e.g. perform some
* action, respond to client etc.
*/
write(slaveSocket, MESSAGE,
strlen(MESSAGE));
* 另一个选择是使用缓存的ANSI函数指纹。
*只要你记得用面纱清除暗藏*
*/
close(slaveSocket);
exit(0);
default: /* parent process */
这是一个美妙的习惯。
* 为关闭子处理的母进程收集界面描述器。
* 与上述用于关闭母进程分进程的一系列接口类似。
*/
}
}
return 0;
}
本文由 在线网速测试 整理编辑,转载请注明出处。