吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3018|回复: 8
收起左侧

[其他原创] socket套接字介绍

[复制链接]
psych1 发表于 2019-11-13 11:21
本帖最后由 psych1 于 2019-11-13 11:33 编辑

0x00 背景介绍

由于最近要完成自己的项目作业,其中需要使用socket进行网络通信。所以简单了解了一些这方面的知识,希望可以抛砖引玉。

0x01 socket介绍

socket 的原意是“插座”,在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。我们把插头插到插座上就能从电网获得电力供应,同样,为了与远程计算机进行数据传输,需要连接到因特网,而 socket 就是用来连接到因特网的工具。
套接字(socket)是一个抽象层,网络套接字是IP地址与端口的组合。学习 socket,也就是学习计算机之间如何通信,并编写出实用健壮的程序。
套接字有很多种类,而最具代表性的就是 Internet 套接字,我们常说的套接字,如果没有其他说明,都是指 Internet 套接字。

0x02 socket类型

根据数据的传输方式,可以将套接字分成两种类型。流格式套接字(SOCK_STREAM)和数据报格式套接字(SOCK_DGRAM)。通过 socket() 函数创建连接时,必须告诉它使用哪种数据传输方式。
流格式套接字是基于TCP协议,TCP 协议会控制你的数据按照顺序到达并且没有错误。所以说流格式套接字是一种可靠的、双向的通信数据流。
流格式套接字有以下特征:

数据在传输过程中不会消失;
数据是按照顺序传输的;
数据的发送和接收不是同步的

数据报格式套接字也是 IP 协议作路由,但是是依托UDP协议。数据报套接字是一种不可靠的、不按顺序传递的、以追求速度为目的的套接字。当数据传输发生错误时,也不会重传。
数据报格式套接字有以下特征:

强调快速传输而非传输顺序;
传输的数据可能丢失也可能损毁;
限制每次传输的数据大小;
数据的发送和接收是同步的。

0x03 网络通信协议

socket是站在传输层的基础上,所以可以使用 TCP/UDP 协议,为了更好的了解socket,我们需要网络通信协议知识的储备,我把附件已经放在下面了,大家可以自取。至少要了解TCP/IP协议,关于TCP的三次握手(这也是面试常问的问题),

0x04 linux与windows系统下socket程序演示

linux系统下比较简单,我们实现一个简单的客户端从服务器读取“Hello World”并打印出来
服务器:

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

int main(){
    //创建套接字
    int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    //将套接字和IP、端口绑定
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
    serv_addr.sin_family = AF_INET;  //使用IPv4地址
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    serv_addr.sin_port = htons(1234);  //端口
    bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    //进入监听状态,等待用户发起请求
    listen(serv_sock, 20);

    //接收客户端请求
    struct sockaddr_in clnt_addr;
    socklen_t clnt_addr_size = sizeof(clnt_addr);
    int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

    //向客户端发送数据
    char str[] = "Hello World";
    write(clnt_sock, str, sizeof(str));

    //关闭套接字
    close(clnt_sock);
    close(serv_sock);

    return 0;
}

客户端:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

int main(){
    //创建套接字
    int sock = socket(AF_INET, SOCK_STREAM, 0);

    //向服务器(特定的IP和端口)发起请求
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
    serv_addr.sin_family = AF_INET;  //使用IPv4地址
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    serv_addr.sin_port = htons(1234);  //端口
    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    //读取服务器传回的数据
    char buffer[40];
    read(sock, buffer, sizeof(buffer)-1);

    printf("Message form server: %s\n", buffer);

    //关闭套接字
    close(sock);

    return 0;
}

windows系统下就比较麻烦了,需要预先加载Winsock.dll 或 ws2_32.dll文件,而且windows跟linux所用的一些函数功能虽然相同,但是名称却是不同的,这个要注意一下。
服务器:

#include <stdio.h>
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib")  //加载 ws2_32.dll

int main(){
    //初始化 DLL
    WSADATA wsaData;
    WSAStartup( MAKEWORD(2, 2), &wsaData);

    //创建套接字
    SOCKET servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    //绑定套接字
    sockaddr_in sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充
    sockAddr.sin_family = PF_INET;  //使用IPv4地址
    sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    sockAddr.sin_port = htons(1234);  //端口
    bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

    //进入监听状态
    listen(servSock, 20);

    //接收客户端请求
    SOCKADDR clntAddr;
    int nSize = sizeof(SOCKADDR);
    SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);

    //向客户端发送数据
    char *str = "Hello World!";
    send(clntSock, str, strlen(str)+sizeof(char), NULL);

    //关闭套接字
    closesocket(clntSock);
    closesocket(servSock);

    //终止 DLL 的使用
    WSACleanup();

    return 0;
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")  //加载 ws2_32.dll

int main(){
    //初始化DLL
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    //创建套接字
    SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    //向服务器发起请求
    sockaddr_in sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充
    sockAddr.sin_family = PF_INET;
    sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    sockAddr.sin_port = htons(1234);
    connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

    //接收服务器传回的数据
    char szBuffer[MAXBYTE] = {0};
    recv(sock, szBuffer, MAXBYTE, NULL);

    //输出接收到的数据
    printf("Message form server: %s\n", szBuffer);

    //关闭套接字
    closesocket(sock);

    //终止使用 DLL
    WSACleanup();

    system("pause");
    return 0;
}

0x05 socket()函数解析

socket()函数在两个平台下参数是相同的,不同的是返回值,大家可以参考上面的代码。
先说一下linux系统下的socket()函数。在 Linux系统下使用 <sys/socket.h> 头文件中 socket() 函数来创建套接字,原型为:

int socket(int af, int type, int protocol);

af指的是地址族(Address Family),也就是ip地址类型。当然有时候也会使用pf,到时候见到就不用惊讶了。type指的是数据传输方式/套接字类型,我们在上面已经讲了,根据数据传输方式的不同,我们可以将socket划分为两种常用类型,这里指的就是这个。protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,分别表示 TCP 传输协议和 UDP 传输协议。
一般情况下有了 af 和 type 两个参数就可以创建套接字了,操作系统会自动推演出协议类型,但是有时候有两种不同的协议支持同一种地址类型和数据传输类型,这个时候我们就需要指定传输协议了。
参数 af 的值为 PF_INET。如果使用 SOCK_STREAM 传输数据,那么满足这两个条件的协议只有 TCP,因此可以这样来调用 socket() 函数:

int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

这种套接字称为 TCP 套接字。

如果使用 SOCK_DGRAM 传输方式,那么满足这两个条件的协议只有 UDP,因此可以这样来调用 socket() 函数:

int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

这种套接字称为 UDP 套接字。

上面两种情况都只有一种协议满足条件,可以将 protocol 的值设为 0,系统会自动推演出应该使用什么协议,如下所示:

int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);  

windows平台下也是如此

SOCKET socket(int af, int type, int protocol);

0x06 小结

希望大家多多支持。不要吝啬你们的评分呀,嘻嘻{:17_1060:}

资料.txt

114 Bytes, 下载次数: 17, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 8吾爱币 +9 热心值 +8 收起 理由
pojielajiruanji + 1 + 1 谢谢@Thanks!
clanns + 1 谢谢@Thanks!
苏紫方璇 + 5 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
sur3 + 1 + 1 我很赞同!
fire0416 + 1 + 1 谢谢@Thanks!
marine153 + 1 + 1 最近也要写一个简单的网络通信程序,收藏着先,有问题还要向你请教呢
MaxMadcc + 1 谢谢@Thanks!
lntuer + 1 life is short,i love Python!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| psych1 发表于 2019-11-13 11:22
滴滴滴!!!平民通道: 链接: https://pan.baidu.com/s/1CRtPoFx35oUAcSL0l5XKYQ 提取码: ma8s 复制这段内容后打开百度网盘手机App,操作更方便哦
pojiedaxia 发表于 2019-11-13 11:48
fire0416 发表于 2019-11-13 13:20
ylrenxd 发表于 2019-11-15 12:48
学习了,很受用,效果就相当于nc命令
vevei_ps 发表于 2019-11-16 13:00
还行不错不错
hanSenWA 发表于 2020-9-8 17:27
链接已经失效,有新的吗
Geekerleon 发表于 2020-9-8 17:32
求补连接
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-22 07:12

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表