linux 网络编程-基础篇

简介:

#Socket简介

是一个编程接口
是一种特殊的文件描述符(everything in Unix is a file)
并不仅限于TCPIP协议
面向连接(Transmission Control Protocol - TCPIP)
无连接(User Datagram Protocol-UDP 和 Inter-Network Packet Exchange-IPX)

#Socket类型
流式套接字(SOCK_STREAM)
提供了一个面向连接,可靠的数据传输服务,数据无差错,无重复的发送且
按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是
字节流,无长度限制
数据报套接字(SOCK_DGRAM)
提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,
数据可能丢失或重复,顺序发送,可能乱序接收
原始套接字(SOCK_RAW)
可以对较低层次协议如IP,ICMP直接访问

#IP地址
IP地址是Internet中主机的标识
Internet中的主机要与别的机器通信必须具有一个IP地址
IP地址为32位(IPV4)或者128位(IPV6)
每个数据包都必须携带目的IP地址和源IP地址,路由器依靠此信息为数据包
选择路由
表示形式:常用点分形式,如202.38.64.10,最后都会转换为一个32位的无符号
整数。

#IP地址的转换
inet_aton()
将strptr所指的字符串转换成32位的网络字节序二进制值
int inet_aton(const char *strptr, struct in_addr *addrptr);
inet_addr()
功能同上,返回转换后的地址
in_addr_t inet_addr(const char *strptr);
inet_ntoa()
将32位网络字节序二进制地址转换成点分十进制的字符串。
char *inet_ntoa(struct in_addr inaddr);

#端口号
为了区分一台主机接收到的数据包应该转交给哪个进程来进行处理,使用端口号
来区分
TCP端口号与UDP端口号独立(协议不同可以使用同一个端口)
三无组:协议,IP,端口
端口号一般由IANA(Internet Assigned Numbers Authority)管理
众所周知端口:1~1023(1~255之间为众所周知端口,256~1023端口通常由
UNIX系统占用
已登记端口:1024~49151
动态或私有端口:49152~65535

#字节序
不同类型CPU的主机中,内存存储多字节整数序列有两种方法,称为主机字节序(HBO):
小端序(little-endian)-低字节存储在低地址
将低字节存储在起始地址,称为"Little-Endian"字节序,Intel,AMD等
采用的是这种方式
大端序(big-endian)-高序字节存储在低地址
将高字节存储在起始地址,称为"Big-Endian"字节序,由ARM,Motorola
等所采用
网络中传输的数据必须按网络字节序,即大端字节序
在大部分PC机上,当应用进程将整数送入socket前,需要转化成网络字节序;当
应用进程从socket取出整数后,要转化成小端字节序

#字节序转换函数
把给定系统所采用的字节序称为主机字节序,为了避免不同类别主机之间在数据
交换时由于对于字节序的不用而导致的差错,引入了网络字节序
主机字节序到网络字节序:
u_long htonl(u_long hostlong);
u_short htons(u_short short);
网络字节序到主机字节序
u_long ntohl(u_long hostlong);
u_short ntohs(u_short short);

#网络编程相关API
int Socket(int domain, int type, int protocol);
int bind(int Sockfd, struct sockaddr *my_addr, int addrlen);
int listen(int sockfd, in backlog);
int accept(int sockfd, struct sockaddr *addr, Socklen_t *addrlen);
int connect(int sockfd, const struct sockaddr *addr, Socklen_t addrlen);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
        const struct sockaddr *dest_addr, Socklen_t addrlen);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
        struct sockaddr *src_addr, Socklen_t *addrlen);
int shutdown(int sockfd, int how);

#command:
netstat -anpt

#地址结构的一般用法
1.定义一个struct sockaddr_in类型的变量并清空
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
2.填充地址信息
myaddr.sin_family = PF_INET;
myaddr.sin_port = htons(8888);
myaddr.sin_addr.s_addr = inet_addr("192.168.1.100");
3.将该变量强制转换为struct sockaddr类型在函数中使用
bind(listenfd,(struct sockaddr *)&myaddr, sizeof(myaddr));

#地址转换函数
unsigned long inet_addr(const char *address);
int inet_aton(const char *cp, struct in_addr *inp);
char *inet_ntoa(struct in_addr in);

socket流程图:

 

 

附:代码

client.c

复制代码
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//uint16_t htons(uint16_t hostshort);
//int atoi(const char *nptr);
//in_addr_t inet_addr(const char *cp);
//void bzero(void *s, size_t n);
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

#include <stdio.h>
#include <sys/types.h>//socket():bind();listen():accept();listen();accept();connect();
#include <sys/socket.h>//socket():bind();listen():accept();inet_addr();listen():accept();connect();
#include <arpa/inet.h>//htons();inet_addr():
#include <netinet/in.h>//inet_addr():
#include <strings.h>//bzero();
#include <stdlib.h>//atoi();exit();
#include <unistd.h>//close():
#include <string.h>

#define N 64

int main(int argc, char *argv[])
{
    if(argc < 3)
    {
        printf("Using: %s ip port\n",argv[0]);
        exit(-1);
    }
    int sockfd;
    struct sockaddr_in myaddr,peeraddr;
    char buf[N] = {0};
    size_t n;
    socklen_t mylen,peerlen;
    mylen = sizeof(myaddr);
    peerlen = sizeof(peeraddr);
    /*  creat socket  */
    if(-1 == (sockfd = socket(AF_INET,SOCK_DGRAM,0)))
    {
        perror("socket");
        exit(-1);
    }
    /* bind initialization */
    bzero(&myaddr,sizeof(myaddr));
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(atoi(argv[2])+1);
    myaddr.sin_addr.s_addr = inet_addr(argv[1]);
    /*      bind      */
    if(-1 == bind(sockfd, (struct sockaddr *)&myaddr, mylen))
    {
        perror("bind");
        exit(-1);
    }
    /*    connect    */
    bzero(&peeraddr, sizeof(peeraddr));
    peeraddr.sin_family = AF_INET;
    peeraddr.sin_port = htons(atoi(argv[2]));
    peeraddr.sin_addr.s_addr = inet_addr(argv[1]);
    //connect(sockfd,(struct sockaddr *)&peeraddr, peerlen);
    while(1){
    fgets(buf, N, stdin);
    printf("buf:%s",buf);
    if(-1 == (n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&peeraddr, peerlen)))
    {
        perror("sendto");
        exit(-1);
    }
    if(strncmp(buf, "quit", 4) == 0)
            break;
    printf("n = %d\n",n);
    }
    close(sockfd);
    exit(0);
}
复制代码

server.c

复制代码
#include <stdio.h>
#include <sys/types.h>//socket():bind();listen():accept();listen();accept();connect();
#include <sys/socket.h>//socket():bind();listen():accept();inet_addr();listen():accept();connect();
#include <arpa/inet.h>//htons();inet_addr():
#include <netinet/in.h>//inet_addr():
#include <strings.h>//bzero();
#include <stdlib.h>//atoi();exit();
#include <unistd.h>//close():
#include <string.h>

#define N 64

typedef struct sockaddr SA;

int main(int argc, char *argv[])
{
    if(argc < 3)
    {
        printf("Using: %s ip port\n",argv[0]);
        exit(-1);
    }

    int listenfd, connfd;
    struct sockaddr_in myaddr, peeraddr;
    char buf[N] = {0};
    size_t n;
    socklen_t mylen, peerlen;
    mylen = sizeof(myaddr);
    peerlen = sizeof(peeraddr);
    /*    create    socket    */
    if ((listenfd = (socket(PF_INET, SOCK_DGRAM, 0))) < 0)
    {
        perror("socket");
        exit(-1);
    }
    /*    bind initialization    */
    bzero(&myaddr, mylen);
    myaddr.sin_family = PF_INET;
    myaddr.sin_port = htons(atoi(argv[2]));
    inet_aton(argv[1], &myaddr.sin_addr);
    
    if(bind(listenfd,(SA *)&myaddr, sizeof(myaddr)) < 0)
    {
        perror("bind");
        exit(-1);
    }
    /*    listen        */
    listen(listenfd, 5);
    /*    accept        */
    if(-1 == (connfd = accept(listenfd, (SA *)&peeraddr, &peerlen)))
    {
        perror("accept");
        exit(-1);
    }
    printf("connect from %s: %d\n",inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));
    /*    recv-send    */
    while(1){
    n = recv(connfd, buf, N, 0);
    buf[n] = 0;
    printf("n = %d---%s\n",n,buf);
    if(0 == strncmp(buf,"quit",4))
    break; send(connfd, buf, strlen(buf), 0); } close(connfd); close(listenfd); exit(0); }
目录
相关文章
|
2月前
|
安全 Linux 网络安全
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
97 0
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
|
3月前
|
运维 Linux 开发者
Linux系统中使用Python的ping3库进行网络连通性测试
以上步骤展示了如何利用 Python 的 `ping3` 库来检测网络连通性,并且提供了基本错误处理方法以确保程序能够优雅地处理各种意外情形。通过简洁明快、易读易懂、实操性强等特点使得该方法非常适合开发者或系统管理员快速集成至自动化工具链之内进行日常运维任务之需求满足。
231 18
|
3月前
|
网络协议 关系型数据库 Linux
【App Service Linux】在Linux App Service中安装 tcpdump 并抓取网络包
在App Service for Linux环境中,无法像Windows一样直接使用网络排查工具抓包。本文介绍了如何通过TCPDUMP在Linux环境下抓取网络包,包括SSH进入容器、安装tcpdump、执行抓包命令及下载分析文件的完整操作步骤。
200 5
|
4月前
|
Web App开发 网络协议 Linux
【Linux】网络基础
TCP/IP五层模型是网络通信的基础框架,将复杂的数据传输过程分为物理层、数据链路层、网络层、传输层和应用层,每层各司其职,协同完成远程通信。该模型确保了不同设备和网络之间的互联互通,是现代互联网运行的核心机制。
295 5
|
4月前
|
网络协议 Linux 开发者
深入Linux中UDP网络通信机制编程探索
以上步骤概述了Linux中UDP网络通信的编程机制。在实现时,因关注细节和上下文环境可能有所调整,但大致流程是一致的。这些知识片段旨在帮助开发者快速上手Linux下的UDP编程,并提供可靠的信息作为编程的基础。在编程实践中,应结合实际业务需求,设计合适的数据传输协议,确保数据的正确性和实时性。
127 0
|
6月前
|
安全 网络协议 Linux
Linux网络应用层协议展示:HTTP与HTTPS
此外,必须注意,从HTTP迁移到HTTPS是一项重要且必要的任务,因为这不仅关乎用户信息的安全,也有利于你的网站评级和粉丝的信心。在网络世界中,信息的安全就是一切,选择HTTPS,让您的网站更加安全,使您的用户满意,也使您感到满意。
193 18
|
6月前
|
Linux 数据安全/隐私保护
使用Linux命令行接入无线网络Wi-Fi的示例。
现在,你已经使用命令行成功地连接到 Wi-Fi 网络了。这两个示例涵盖了用 `nmcli` 和 `wpa_supplicant` 连接无线网络的常见场景,让你能够不依赖图形化界面来完成这个任务。在日常使用中熟练掌握这些基本操作能增强你对 Linux 系统的理解,帮助你更有效地处理各种问题。
450 12
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
433 2
|
6月前
|
安全 Ubuntu Linux
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
217 0
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
|
8月前
|
Ubuntu Linux
Linux系统管理:服务器时间与网络时间同步技巧。
以上就是在Linux服务器上设置时间同步的方式。然而,要正确运用这些知识,需要理解其背后的工作原理:服务器根据网络中的其他机器的时间进行校对,逐步地精确自己的系统时间,就像一只犹豫不决的啮齿动物,通过观察其他啮齿动物的行为,逐渐确定自己的行为逻辑,既简单,又有趣。最后希望这个过程既能给你带来乐趣,也能提高你作为系统管理员的专业素养。
1278 20