最后更新:2021-11-29 17:24:51 手机定位技术交流文章

IP 地址分为两个部分, 网络ID 字段和 HostID 字段。 分解后, IP 地址被分类为 A- E 。 例如, B 类中的IP 地址被分为16位网络ID, 其中前两位为 10, 后一位是 16 位 HostID 字段。 发送到 IP 地址的软件包先被发送到与同一网络WorkingID 相同的路由器。 路由器将通过 HostID 将软件包转发给网络中的特定主机 。 每个主机都有一个本地主机名, 本地主机, 以及默认的 IP 地址 。 本地主机链层是一个返回虚拟设备, 将每个数据包返回同一本地主机 。 此功能允许我们在同一计算机上运行 TCP/ IP 应用程序, 而不实际连接互联网 。
IP 协议用于在 IP 主机之间发送/接收数据包 。 IP 主机仅将软件包传送给接收者, 但不保证软件包将转移到目的地或连续发送。 这意味着 IP 不是一个可靠的协议 。 如果需要可靠性, 必须在 IP 层上方提供 。
UDP(用户数据报告协议)(RFC768,1980年;Comer 1988年)是一个关于IP的协议,用于传输和接收数据报告。 和IP一样,UDP并不保证可靠性,而是快速有效的,可以在可靠性并不关键的情况下使用。
TCP(传输控制协议)是用于传输/接收数据流的以连接为导向的协议。 TCP也可能在 IP 上运行,但它提供一致的数据传输。 UDP通常用于发送邮件,但TCP被用于发送数据流。
应用程序 = (主机IP地址、协议和端口)
协议是 TCP 或 UDP, 端口号是分配给程序的唯一未签名的短整数 。 要使用 UDP 或 TCP, 应用程序( process) 必须首先选择或获得端口号 。 保留了第一个 1024 端口号 。 其他端口号可供一般使用 。 应用程序可以选择可用的端口号, 也可以在操作系统中进行核分配 。
(1)套接字地址
struct sockaddr_in {
sa_family_t sin_family; // AF_INET for TCP/IP
// port number
in_port_t sin_port;
struct in_addr sin_addr;// IP address );
// internet address struct in_addr {
// IP address in network byte order
s_addr;
uint32_t
);
(2)套接字API
服务器必须构造套接字, 并将其绑在带有服务器 IP 地址和端口号的套接字地址上。 它可以使用预设端口号码, 或者使操作系统能够选择端口号码( 如果罪过端口为零 ) 。 为了连接服务器, 客户端必须创建一个套接字 。 对于 UPD 设置, 您可以将其附加到服务器 地址构建器上。 对于 UPD 设置, 您可以将套接字附加到服务器 地址和端口号的套接字地址上。 它可以使用预设端口号码, 或者使操作系统能够选择端口号( 如果罪过端口为零 ) 。 为了连接服务器, 客户端口必须创建套接字。 For UPD 设置, 您可以将其附加到服务器地址 。
#include <stdio.h>
#include <arpa/inet.h>//inet_addr() sockaddr_in
#include <string.h>//bzero()
#include <sys/socket.h>//socket
#include <unistd.h>
#include <stdlib.h>//exit()
#define BUFFER_SIZE 1024
int main() {
char listen_addr_str[] = "0.0.0.0";
size_t listen_addr = inet_addr(listen_addr_str);
int port = 8080;
int server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_size;
char buffer[BUFFER_SIZE];//缓冲区大小
int str_length;
server_socket = socket(PF_INET, SOCK_STREAM, 0);//创建套接字
bzero(&server_addr, sizeof(server_addr));//初始化
server_addr.sin_family = INADDR_ANY;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = listen_addr;
if (bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
printf("绑定失败n");
exit(1);
}
if (listen(server_socket, 5) == -1) {
printf("监听失败n");
exit(1);
}
printf("创建tcp服务器成功n");
fd_set reads,copy_reads;
int fd_max,fd_num;
struct timeval timeout;
FD_ZERO(&reads);//初始化清空socket集合
FD_SET(server_socket,&reads);
fd_max=server_socket;
while (1) {
copy_reads = reads;
timeout.tv_sec = 5;
timeout.tv_usec = 5000;
//无限循环调用select 监视可读事件
if((fd_num = select(fd_max+1, ©_reads, 0, 0, &timeout)) == -1) {
perror("select error");
break;
}
if (fd_num==0){//没有变动的socket
continue;
}
for(int i=0;i<fd_max+1;i++){
if(FD_ISSET(i,©_reads)){
if (i==server_socket){//server_socket变动,代表有新客户端连接
addr_size = sizeof(client_addr);
client_socket = accept(server_socket, (struct sockaddr *) &client_addr, &addr_size);
printf("%d 连接成功n", client_socket);
char msg[] = "恭喜你连接成功";
write(client_socket, msg, sizeof(msg));
FD_SET(client_socket,&reads);
if(fd_max < client_socket){
fd_max=client_socket;
}
}else{
memset(buffer, 0, sizeof(buffer));
str_length = read(i, buffer, BUFFER_SIZE);
if (str_length == 0) //读取数据完毕关闭套接字
{
close(i);
printf("连接已经关闭: %d n", i);
FD_CLR(i, &reads);//从reads中删除相关信息
} else {
printf("%d 客户端发送数据:%s n", i, buffer);
write(i, buffer, str_length);//将数据发送回客户端
}
}
}
}
}
return 0;
}
本文由 在线网速测试 整理编辑,转载请注明出处。