socket编程步骤

java-基本的Socket编程-实现服务器端和客户端通信 基本的Socket编程: 本实例介绍Socket编程的基本步骤。启动Socket服务后,再打开Socket刻画段,在输入框中输入消息,然后发送给服务器端,服务器端将收到的消息返回到客户端。关键技术: Socket编程的关键技术如下; —–Socket服务器端需要在某个端口上开启服务端类型的Socket,即java.net.ServerSocket。通过他的accept方法等待并接收客户端的请求 阅读详情

目录

 

服务器端

第一步:创建用于监听的套接字

第二步:将套接字与本机IP地址和端口号绑定

第三步:设置监听

第四步:等待并接收连接请求

第五步:C/S网络通信

第六步:关闭文件描述符

客户端

第一步:创建套接字

第二步:连接服务器

第三步:通信


服务器端

第一步:创建用于监听的套接字

#include <sys/types.h>         
#include <sys/socket.h>

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

      domain:地址族,常用有AF_INET和AF_INET6,分别代表IPv4和IPv6

      type:数据传输方式/套接字类型,常用SOCK_STREAM(流格式套接字/面向连接的套接字),SOCK_DGRAM(数据报套接字/无连接的套接字)

      protocol:传输协议,常用IPPROTO_TCP,IPPROTO_UDP,分贝代表TCP和UDP协议

type与protocol不能冲突,即如果使用面向连接的套接字,那么protocol就得是TCP协议。通常protocol参数可以直接填0,这样系统会自动推导出要使用得协议。

int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);  //创建TCP套接字
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);  //创建UDP套接字

      返回值:成功返回文件描述符(当前进程文件描述符表中最小可用的文件描述符),失败返回-1并设置errno。

第二步:将套接字与本机IP地址和端口号绑定

因为套接字相当于是一个在内核中打开的文件,也就是内存中的一篇缓冲区,现在我们要将该缓冲区与本地IP地址和端口号绑定。

首先将IP地址和端口号放入sockaddr_in结构体变量之中

struct sockaddr_in {
    short int sin_family;                      /* Address family */
    unsigned short int sin_port;       /* Port number */
    struct in_addr sin_addr;              /* Internet address */
    unsigned char sin_zero[8];         /* Same size as struct sockaddr */
};

首先定义结构体变量:

struct sockaddr_in serv_addr;

sin_family是使用的地址协议族,一般是AF_INET,即IPv4协议

serv_addr.sin_family = AF_INET;

sin_port是端口号,htons()函数表示将16位的短整数从主机字节序变成网络字节序(即大端模式)。

serv_addr.sin_port = htons(9999); // 本地端口,25536以下

sin_addr存储IP地址,但是不是直接存储成整型数之类的,而是存储到in_addr结构体中。

in_addr结构体如下,可以保存一个32位的IP地址,明明可以直接用,还非要放到一个结构体中,据说是上古时期实现这个东西的程序员想多了。

struct in_addr {
    unsigned long s_addr;
};

这里INADDR_ANY即0.0.0.0,即任意地址,因为有些主机有多块网卡可以连到多个网络有不同ip,这样设置可以让服务器程序监听多个网卡ip地址的端口,也可以理解为用多个ip地址监听同一个端口。

serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 

sin_zero是为了让sockaddr结构体与sockaddr_in结构体大小相同,而特意保留的空字节。

将IP地址和端口号放入sockaddr_in结构体变量之后就可以用bind函数将套接字变量和ip,端口号绑定。

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr,
           socklen_t addrlen);

sockfd:用于监听的套接字文件描述符

addr:是sockaddr结构体类型的变量地址,前边我们是用sockaddr_in结构体来设置的IP地址和端口号,需要强制类型转换成为sockaddr类型的地址。之所以不直接用sockaddr来设置IP地址和端口号是有原因的,struct sockaddr是通用的套接字地址形式,而不同的网络体系表示地址的方法是不同的,struct sockaddr_in是在通用的套接字地址形式的基础上,针对TCP/IP设计的套接字的地址形式,里面多了两个成员,也就是IP号和端口号,这样方便我们填充。

addrlen:sockaddr_in结构体变量的大小。

int ret = bind(lfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

成功返回0,失败返回-1并设置errno

第三步:设置监听

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int listen(int sockfd, int backlog);

sockfd:文件描述符

backlog:未完成连接队列和已完成连接队列的上限,暂时理解为对客户端连接数量的限制。

成功返回0,失败返回-1

ret = listen(lfd, 64);

     

第四步:等待并接收连接请求

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

sockfd:用于监听的套接字文件描述符

addr:sockaddr类型的传出参数,存放客户端的套接字变量信息

addrlen:addr的大小

addr与addrlen都是可选参数

返回值:

       如果监听的队列中无等待连接,且套接字为阻塞,则等待连接到来

       如果监听的队列中无等待连接,且套接字为非阻塞,则返回-1并设置errno

       如果监听的队列中有等待连接,则取出第一个连接,返回一个与用于监听的套接字同等类型的套接字(本质是一个文件描述符,用于通信)。

 // 等待并接收请求连接请求
    struct sockaddr_in cline_addr;
    socklen_t clien_len = sizeof(cline_addr);
    int cfd = accept(lfd, (struct sockaddr*)&cline_addr, &clien_len);
    if(cfd == -1){
        perror("accept error");
        exit(1);
    }

接收到连接请求之后可以输出展示一下,注意要把ip地址的格式转化成字符串输出

#include <arpe/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);     //将点分十进制的ip地址转化为用于网络传输的数值格式
        返回值:若成功则为1,若输入不是有效的表达式则为0,若出错则为-1
 
const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);     //将数值格式转化为点分十进制的ip地址格式
        返回值:若成功则为指向结构的指针,若出错则为NULL
char ipbuf[64];
    printf("client ip: %s, port: %d\n", inet_ntop(AF_INET, &cline_addr.sin_addr.s_addr, ipbuf, sizeof(ipbuf)), ntohs(cline_addr.sin_port));

第五步:C/S网络通信

上边的过程只是通过套接字将服务器端和客户端连接了起来,具体的通信就是服务器端进程和客户端进程之间的通信,与普通的unix IO并没有区别,也是通过文件描述符与相关的系统调用进行读写。即像操作普通文件一样用read来读取客户端发送的内容,用write来向客户端写内容。

第六步:关闭文件描述符

关闭用于监听和用于通信的文件描述符。

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

int main(int argc, const char* argv[]){
    // 创建用于监听的套接字
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    if(lfd == -1){
        perror("socker error");
        exit(1);
    }

    // 套接字与IP和端口绑定
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(9999); // 本地端口,25536以下
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定IP?

    int ret = bind(lfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    if(ret == -1){
        perror("bind error");
        exit(1);
    }

    // 设置监听
    ret = listen(lfd, 64);
    if(ret == -1){
        perror("listen error");
        exit(1);
    }
    
    // 等待并接收请求连接请求
    struct sockaddr_in cline_addr;
    socklen_t clien_len = sizeof(cline_addr);
    int cfd = accept(lfd, (struct sockaddr*)&cline_addr, &clien_len);
    if(cfd == -1){
        perror("accept error");
        exit(1);
    }

    char ipbuf[64];
    printf("client ip: %s, port: %d\n", inet_ntop(AF_INET, &cline_addr.sin_addr.s_addr, ipbuf, sizeof(ipbuf)), ntohs(cline_addr.sin_port));
    

    // 通信
    while(1){
        // 先接收数据
        char buf[1024] = {0};
        int len = read(cfd, buf, sizeof(buf));
        if(len == -1){
            perror("read error");
            break;
        }else if(len > 0){
            // 顺利读出数据
            printf("read buf = %s\n", buf);
            // 数据小写变大写
            for(int i = 0; i < len; ++i){
                buf[i] = toupper(buf[i]);
            }
            printf("大写转换结果:%s\n", buf);
            // 大写数据发回给客户端
            write(cfd, buf, strlen(buf) + 1);
        }else if(len == 0){
            printf("client disconnect \n");
            break;
        }
    }

    close(lfd);
    close(cfd);


}

 

 

客户端

第一步:创建套接字

 int fd = socket(AF_INET, SOCK_STREAM, 0);

第二步:连接服务器

先定义sockaddr_in结构体变量来设置ip和端口号

注意这里的ip是服务器端的ip,端口号也是服务器进程对应的端口号

inet_pton用来设置ip地址,可以把字符串变成二进制网络字节序,这里的“127.0.0.1”是本地环回地址,因为我们的服务器进程也在本机上,因此要使用本地环回。

struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(9999); // 在服务器进程中设置的端口?
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);

接下来是使用connect函数连接服务器,当使用tcp协议的时候,connect会完成三次握手的过程

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);

sockfd:客户端进程套接字的文件描述符

addr:服务端的ip和端口号结构变量地址,但是需要注意强转,因为我们定义的都是sockaddr_in变量,而使用的参数类型是sockaddr类型的。

addrlen:结构变量的大小

成功返回0,失败返回-1

int ret = connect(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    if(ret == -1){
        perror("connect error");
        exit(1);
    }

第三步:通信

在服务端进程中,监听和通信用的是两个不同的套接字,而在客户端只需要一个通信套接字就可以,不需要监听的。

注意strlen()函数计算字符串长度是不包括最后的‘\0’

 while(1){
        // 写数据
        // 接收键盘输入
        char buf[512];
        fgets(buf, sizeof(buf), stdin);
        // 发送给服务器
        write(fd, buf, strlen(buf) + 1);
        // 接收服务器端的数据
        int len = read(fd, buf, sizeof(buf));
        printf("read buf = %s, len = %d\n", buf, len);
    }
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>

int main(int argc, const char* argv[]){
    // 创建套接字
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd == -1){
        perror("socker error");
        exit(1);
    }

    // 连接服务器
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(9999); // 在服务器进程中设置的端口?
    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);
    int ret = connect(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    if(ret == -1){
        perror("connect error");
        exit(1);
    }
    // 通信
    while(1){
        // 写数据
        // 接收键盘输入
        char buf[512];
        fgets(buf, sizeof(buf), stdin);
        // 发送给服务器
        write(fd, buf, strlen(buf) + 1);
        // 接收服务器端的数据
        int len = read(fd, buf, sizeof(buf));
        printf("read buf = %s, len = %d\n", buf, len);
    }
    return 0;
}

 

linux系统编程_socket网络编程 服务器需要先创建Socket对象并将其绑定到本地IP地址和端口号,然后监听客户端连接请求,并创建新的Socket对象进行数据传输。4. 接受连接请求:当客户端请求连接时,服务器应用程序通过accept()函数接受连接请求,并创建一个新的Socket对象来处理客户端的请求。1. 创建Socket对象:使用Socket库中提供的函数创建一个Socket对象,它代表着一个网络通信端点,包括IP地址和端口号。如果返回-1,表示接收失败。是一个通用的地址结构体,根据协议族的不同,需要将其转换为对应的具体结构体,如。 阅读详情

相关推荐

Socket 网络编程学习指南

Socket(套接字)是网络通信的端点,用于不同设备或进程之间的数据传输。

浩瀚之水的专栏 1254

Socket编程详解:从基本概念到实例应用(TCP|UDP C语言实例详解)

Socket编程详解:从基本概念到实例应用

深耕嵌入式领用多年, 致力于分享嵌入式领域技术! 2万+

巨量千川M-API实战:5分钟搞定短视频计划数据自动获取(Python版)

本文详细介绍了如何利用巨量千川M-API和Python快速搭建自动化工具,实现短视频计划数据的自动获取。通过实战代码演示了从环境准备、Token管理到核心数据接口调用的完整流程,帮助电商运营和技术开发者告别手动导出,高效完成数据汇总与分析。

weixin_29325515的博客 1357

Socket编程基础

socket网络编程的基本知识

u010140427的博客 4138

11种图像清晰度评价函数附MATLAB代码

博主的第一篇博客! 本科毕业论文是“基于图像处理的自动对焦技术研究”,对焦过程中的一个重要阶段是图像清晰度评价,博主自己用MATLAB实现了4类清晰度评价函数:基于图像梯度的清晰度评价函数、频域评价函数、信息熵评价函数、统计学评价函数,总计11种。博主之前没有用过MATLAB,完全是本科论文需要,没办法对着别人的代...

kungfu_rabbit的博客 5万+

王珊数据库系统概论第5版视频教材

目录 隐藏 说明:本课程共包括1种电子书、84个高清视频(共68课时)、1种纸质书(赠品)。 网授课程 王珊《数据库系统概论》(第5版)网授精讲班【共68课时】 序号 名称 课时 1 第1章 绪 论(1) 00:32:25 2 第1章 绪 论(2) 00:17:03 3 第1章 绪 论(3) 00:50:19 4 第1章 绪 论(4) 00:20:37 5 第1章 绪 论(5) 00:24:47 6 第2章 关系数据库(1) 00:47:23 7 第2章 关系数据库(2) 00:14:48 8 第2章 关系

mrtaoy96的博客 1145

C++ Socket编程步骤

转自https://www.cnblogs.com/chencaiming/p/7249904.html sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);基于TCP的socket编程是采用的流式套接字。 服务器端编程的步骤: 1:加载套接字库,创建套接字(WSAStartup()/socke...

透明 2万+

GameFramework框架详解之 框架总览

一.前言 目前市场上有很多优秀个开源框架,比如ET,GameFramework,DBFramework,StrangeIOC,Loxodon-Framework,KSFramework,xluaFramework等等。其中要说规范的话,不得不说GameFramework还是不错的,当然很多新手看到后会觉的有点复杂,写一个小小的功能,不得不套用一堆东西,继承一堆接口,感觉不知所措,不能随心所欲的去撸代码。其实这个框架就是为了约束新手的行为的,让我们面向接口编程,遵循“开闭”的设计原则来写代码,方便后期的扩

TxNet 2万+

Socket基于TCP和UDP编程基本步骤

TCP编程的服务器端一般步骤是:   1、创建一个socket,用函数socket();   2、设置socket属性,用函数setsockopt(); * 可选   3、绑定IP地址、端口等信息到socket上,用函数bind();   4、开启监听,用函数listen();   5、接收客户端上来的连接,用函数accept();   6、收发数据,用函数send()和recv(),...

u011339364的专栏 3087

30. 如何使用 SEGW 的 redefine 功能对 SAP 标准 OData 服务进行扩展

SAP 发布了很多标准的 Fiori 应用,可以通过笔者的文章里提到的进行浏览。比如 My Opportunities 就是 SAP CRM 领域的一个 Fiori 应用:下图是 Opportunity 明细页面的 Info 标签页:假设我们想在这些标准字段的末尾增添一个新字段 Created By,用来维护当前 Opportunity 的创建者。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1170

RockChip Android14 修改LCD背光最大值

在调试LCD屏时时长会出现硬件不匹配,导致电流过大,屏幕发热严重。在不调整硬件的情况下,我们可以通过修改软件,降低LCD背光最大值来实现适配。我们都知道LCD屏背光是靠pwm来控制,一般来说最大值可以设置为255,针对上述问题,我们可以通过软件来降低该值,比如200,100等等。

qq_34968572的博客 631

linux socket编程步骤,C++ Socket编程步骤

sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);基于TCP的socket编程是采用的流式套接字。服务器端编程的步骤:1:加载套接字库,创建套接字(WSAStartup()/socket());2:绑定套接字到一个IP地址和一个端口上(bind());3:将套接字设置为监听模式等待连接请求(listen(...

weixin_31106267的博客 207

HighTec安装使用

HighTec安装使用

qq_43552564的博客 3833

Socket编程步骤

最近公司的流媒体服务器交给我修改,主要问题是只能使用独立的ip的海康威视摄像头接入(海康威视能直接使用rtsp协议获取视频数据),用tutk的p2p方式获取视频数据有点问题。 我还是先了解下socket的交互过程吧,转账了一篇文章,给自己做个笔记 sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW

maweisky531的专栏 770

人工智能大模型原理与应用实战:AI模型转换为API的步骤和方法

传统的开发模式下,构建复杂的软件系统是非常费时费力的,而通过云计算、微服务等技术手段可以实现快速部署、弹性扩展的能力。在这种背景下,越来越多的公司将重点转移到研发人员的产品思维上,希望能够将自己的AI模型转换为一个可供他人调用的API接口。但是对于许多从事AI领域的研发人员来说,如何将自己的AI模型转换为API是一个比较棘手的问题。在这篇文章中,作者将从AI模型转换为API的过程分为以下几个步骤:AI模型准备阶段——模型选择、数据准备、模型训练。

AI天才研究院 2598

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

socket 编程基本步骤

sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);基于TCP的socket编程是采用的流式套接字。 服务器端编程的步骤: 1:加载套接字库,创建套接字(WSAStartup()/socket()); 2:绑定套接字到一个IP地址和一个端口上(bind()); 3:将套接字设置为监听

雄鹰 工作室 3803

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

vc中socket编程步骤及实例

sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);基于TCP的socket编程是采用的流式套接字。在这个程序中,将两个工程添加到一个工作区。要链接一个ws2_32.lib的库文件。服务器端编程的步骤:1:加载套接字库,创建套接字(WSAStartup()/socket());2:绑定套接字到一个IP地址和一个端口上(bind());3:将套接字设置为监听模式等待连接请求(listen());4:请求到来后,接受连接

1393

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

java socket 步骤_基于TCP的socket编程步骤(java)

1. 编程原理1.1服务器端(1) 创建ServerSocket对象,绑定监听端口;(2) 通过accept()方法监听客户端请求;(3) 连接建立后,通过输入流读取客户端发送的请求信息;(4) 通过输出流向客户端发送相应信息;(5) 关闭响应资源。1.2 客户端(1) 创建Socket对象,指明需要连接的服务器地址和端口;(2) 连接建立后,通过输出流向服务器端发送请求信息;(3) 通过输入流获...

weixin_39578516的博客 893
上一篇: 数组与指针
下一篇: C++翻转链表
罗古洞的女婿
博客等级 码龄10年 1117粉丝 125原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值