TCP/IP网络编程 学习笔记_1 --网络编程入门

article/2025/9/26 16:53:25

前言:这个系列网络编程教程实例代码是在Xcode上运行的,MacOSX,是一个基于UNIX核心的系统,所以基于Linux的网络编程代码一般可以直接在Xcode上运行,如果要移植到Windows其实就只需要稍微改下,本章下面有讲Windows上的不同之处。

网络编程和套接字

  • 网络编程其实和我们计算机上的文件读取操作很类似,通俗地讲,网络编程就是编写程序使两台联网的计算机相互交换数据。那么,数据具体怎么传输呢?其实操作系统会提供名为“套接字”的部件,套接字就是网络数据传输用的软件设备而已。即使你对网络数据传输原理不太熟悉,你也可以通过套接字完成数据传输。因此,网络编程常常又称为套接字编程。

  • 下面我们再通过一个通俗地例子来理解什么是套接字并给出创建它的过程。实际上,这个过程类似我们的电话机系统,电话机通过固定电话网完成语言数据的交换。这里的电话机就类似我们的套接字,电网就类似我们的互联网。和电话可以拨打或接听一样,套接字也可以发送或接收。先来看看接收的套接字创建过程:
    1,打电话首先需要准备什么?当然得是要先有一台电话机。创建相当于电话机的套接字,如下:

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

    2,准备好电话机后要考虑分配电话号码的问题,这样别人才能联系到你。套接字也一样,利用下面函数创建好套接字分配地址信息(IP地址和端口号)。

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

    3,做了上面两步后,接下来就是需要连接电话线并等待来电。一连接电话线,电话机就转为了可接听状态,这时其他人可以拨打电话请求连接到该机了。同样,需要把套接字转化成可接收连接的状态。

    int listen(int sockfd, int backlog);

    4,前面都做好后,如果有人拨打电话就会响铃,拿起话筒才能接听电话。套接字同样如此,如果有人为了完成数据传输而请求连接,就需要调用下面函数进行受理。

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

  • 总结下网络中接收连接请求的套接字创建过程如下:
    第一步:调用socket函数创建套接字。
    第二步:调用bind函数分配IP地址和端口号。
    第三部:调用listen函数转为可接收请求状态。
    第四步:调用accept函数受理连接请求。

  • 上面讲的都是接电话,即服务端套接字(接收),下面我们再来讲讲打电话,即客服端套接字(发送)。这个要简单,只有两步:1,调用socket函数创建套接字。2,调用connect函数向服务端发送连接请求。

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

基于Linux的文件操作

1,在这里为什么要讨论Linux上的文件操作呢?因为Linux上,socket操作与文件操作没有区别,在Linux上,socket也被认为是文件的一种。
注:Linux上的C语言编译器–GCC,具体使用就不在这里讲了。

2,文件描述符:是系统自动分配给文件或套接字的整数。下面我们再来通过一个例子理解下它:假设学校有个打印室,只需要打个电话就能复印所需论文。有一位同学,经常打电话要复印这样个内容:“<<关于随着高度信息化社会而逐渐提升地位的触觉,知觉,思维,性格,智力等人类生活质量相关问题特性的人类学研究>>这篇论文第26页到30页”。终于有一天,打印室的人感觉这样太不方便了,于是,打印室的人和那位同学说:“以后那篇论文就编为第18号,你就说帮我复印18号论文26页到30页”。在该例中,打印室相当于操作系统,那位同学相当于程序员,论文号相当于文件描述符,论文相当于文件或套接字。也就是说,每当生成文件或套接字,操作系统就会自动返回给我们一个整数。这个整数就是文件描述符,即创建的文件或套接字的别名,方便称呼而已。
注:文件描述符在Windows中又称为句柄。

3,Linux上的文件或套接字操作:
打开文件:

int open(const char *path, int flag); –> (Linux上对应socket(…)函数)

关闭文件或套接字:

int close(int fd); –>(Windows上对应closesocket(SOCKET S)函数)

将数据写入文件或传递数据:

ssize_t write(int fd, const void *buf, size_t nbytes);

读取文件中数据或接收数据:

ssize_t read(int fd, void *buf, size_t nbytes);

注释:ssize_t = signed int, size_t = unsigned int,其实它们都是通过typedef声明的,为基本数据类型取的别名而已。既然已经有了基本数据类型,那么为什么还需要为它取别名呢?是因为目前普遍认为int是32位的,而过去16位操作系统时代,int是16位的。根据系统的不同,时代的变化,基本数据类型的表现形式也随着变化的。如果为基本数据类型取了别名,以后要修改,也就只需要修改typedef声明即可,这将大大减少代码变动。

基于Windows平台的实现

1,Windows套接字大部分是参考BSD系列UNIX套接字设计的,所以很多地方都跟Linux套接字类似。因此,只需要更改Linux环境下编好的一部分网络程序内容,就能再Windows平台下运行。

2,上面讲了Linux上,文件操作和套接字操作一致。但Windows上的I/O函数和套接字I/O函数是不同的。
Winsock数据传输函数:

int send(SOCKET s, const char *buf, int len, int flags);

Winsock数据接收函数:

int recv(SOCKET s, const char *buf, int len, int flags);

3,Windows与Linux上的套接字再一个区别是:Windows上需要先对Winsock库进行初始化,最后退出还要注销Winsock相关库。

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
第一个参数:Winsock中存在多个版本,应准备WORD类型的(WORD是typedef声明的unsigned short)套接字版本信息。若版本为1.2,则其中1是主版本号,2是副版本号,应传递0x0201。高8位为副版本号,低8位为主版本号。我们还可以直接使用宏,MAKEWORD(1,2); //主版本号为1,副版本为2,返回0x0201。
第二个参数:就是传入WSADATA型结构体变量地址。

Winsock库初始化:

int main(int  argc, char *argv[])
{WSADATA wsaData;...if(WSAStartup(MAKEWORD(1,2), &wsaData) != 0)ErrorHandling("WSAStartup() error!");...return 0;
}

在退出时需要释放Winsock库:

int WSACleanup(void); //返回0成功,失败返回SOCKET_ERROR

Linux上代码实例

  • 服务端:
//
//  main.cpp
//  hello_server
//
//  Created by app05 on 15-7-6.
//  Copyright (c) 2015年 app05. All rights reserved.
///*1,argv[]默认它只有一个参数就是程序名,那么怎么手动给它添加参数呢?首先要清楚给它添加参数是为了用命令行参数就算以后要修改这个参数就只要编译器工具里设置下就可以了而不需要改代码,如端口设置。2,在Xcode中给程序提供命令行参数步骤:Product菜单-->Scheme-->Edit Scheme-->Run-->Arguments-->+添加*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, const char * argv[]) {int serv_sock;int clnt_sock;struct sockaddr_in serv_addr;struct sockaddr_in clnt_addr;socklen_t clnt_addr_size;char message[] = "Hello World!";if(argc != 2){printf("Usage:%s <port>\n", argv[0]);exit(1);}serv_sock = socket(PF_INET, SOCK_STREAM, 0);if(serv_sock == -1)error_handling("socket() error");memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(atoi(argv[1]));if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)error_handling("bind() error");if(listen(serv_sock, 5) == -1)error_handling("listen() error");clnt_addr_size = sizeof(clnt_addr);//如果没有收到请求,则不返回,只到有连接请求为止clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size);if(clnt_sock == -1)error_handling("accept() error");write(clnt_sock, message, sizeof(message));close(clnt_sock);close(serv_sock);return 0;
}
  • 客服端:
//
//  main.cpp
//  hello_client
//
//  Created by app05 on 15-7-6.
//  Copyright (c) 2015年 app05. All rights reserved.
///*1,如果服务端和客服端是同一台电脑,那么IP地址可以填:127.0.0.1,如果不在同一台电脑上,则应该填服务端电脑IP。2,运行时,先运行服务端程序,然后再运行客服端程序。*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, const char * argv[]) {int sock;struct sockaddr_in serv_addr;char message[30];int str_len;if(argc != 3){printf("Usage: %s <IP> <port>\n", argv[0]);exit(1);}sock = socket(PF_INET, SOCK_STREAM, 0);if(sock == -1)error_handling("socket() error");memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port = htons(atoi(argv[2]));if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)error_handling("connect() error");str_len = read(sock, message, sizeof(message) - 1);if(str_len == -1)error_handling("read() error");printf("Message from server: %s \n", message);close(sock);return 0;
}

这里写图片描述


http://chatgpt.dhexx.cn/article/jFjMJAwa.shtml

相关文章

Scratch编程入门

Scratch编程入门 Scratch是麻省理工学院的“终身幼儿园团队”&#xff08;Lifelong Kindergarten Group&#xff09;开发的图形化编程工具&#xff0c;免费。2019年1月2日正式发布, Scratch3.0。 Scratch把计算机执行的指令、逻辑变成了小朋友能看明白的“积木”&#xff0c;…

C语言网络编程——基础

OSI七层参考模型 是理想化的并没有完全实现的模型。 应用层 提供响应的应用服务 表示层 数据的表示和加密 会话层 建立会话关系 传输层 通过传输协议传输数据 网络层 实现跨子网通信&#xff0c;路由转发&#xff0c;维护路由表。 数据链路层 实现以太网内数据帧的转发 …

matlab 神经网络编程入门系列(1)

本文主要内容包括&#xff1a; (1) 介绍神经网络基本原理&#xff0c;(2) Matlab实现前向神经网络的方法 。 第0节、引例 本文以Fisher的Iris数据集作为神经网络程序的测试数据集。 由于英文的类无法识别&#xff0c;故需要把对应的类用数字标识&#xff0c;数据集变成&…

WinPcap网络编程入门——0. 环境配置及系列介绍

WinPcap网络编程入门——0. 环境配置及系列介绍 系列教程章节直达&#xff1a; Winpcap网络编程入门——1. 获取设备列表&#xff1b; 说明&#xff1a;本教程适用于网络编程开发人员入门&#xff0c;将从底层分析 WinPcap 的执行过程&#xff0c;结合一些实际用例来学习 WinP…

Java核心类库之(网络编程:网络编程入门、UDP通信程序、TCP通信程序)

目录 1 网络编程入门1.1 网络编程概述1.2 网络编程三要素1.3 IP地址1.4 InetAddress的使用1.5 端口1.6 协议 2 UDP通信程序2.1 UDP通信原理2.2 UDP发送数据2.3 UDP接收数据2.4 范例 3 TCP通信程序3.1 TCP通信原理3.2 TCP发送数据3.3 TCP接收数据3.4 案例3.4.1 练习一&#xff1…

Java网络编程入门(软件结构、网络通信协议、网络编程三要素)

文章目录 &#x1f415;软件结构&#x1f436;网络通信协议&#x1f981;协议分类&#x1f405;网络编程三要素&#x1f406;协议&#x1f40e;IP地址&#x1f98c;端口号 &#x1f415;软件结构 C/S结构 &#xff1a;全称为Client/Server结构&#xff0c;是指客户端和服务器结…

黑客编程入门 之 网络编程入门

网络编程入门 前言Socket技术详细介绍Socket 编程所需函数服务器/客户 代码 前言 “任何职业都可以成为黑客。你可以是一个木匠黑客。不一定是高科技。只要与技能有关&#xff0c;并且倾心专注于你正在做的事情&#xff0c;你就可能成为黑客。” ——引自《黑客伦理与信息时代精…

WinPcap网络编程入门——1. 获取设备列表

WinPcap网络编程入门——1. 获取设备列表 系列教程章节直达&#xff1a; Winpcap网络编程入门——1. 获取设备列表&#xff1b; 上节中我们简单介绍了 WinPcap 的相关资料&#xff0c;配置好了开发环境&#xff0c;现在就让我们正式开始网络编程开发吧&#xff01; 1. 基本开…

网络编程入门(代码很详细)

网络编程 1.1概述 计算机网络&#xff1a;计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软件及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算…

网络编程——(1)网络编程入门

一、软件架构 1.1C/S结构&#xff1a; 全称Client/Server结构&#xff0c;是指客户端和服务器结构。常见的程序有QQ、迅雷等。 1.2 B/S结构&#xff1a; 全称为Browser/Server结构&#xff0c;是指浏览器和服务器结构。常见浏览器有谷歌、火狐等。 两种架构各有优势&#xf…

网络编程入门

1.网络编程入门 1.1网络编程概述 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软件及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算机系统 网…

线性代数学习笔记——第六讲——矩阵的转置

1. 矩阵转置的定义&#xff08;矩阵的行和列互换位置&#xff09; 2. 矩阵转置的性质之一&#xff1a;矩阵转置一次后再转置一次&#xff0c;等于矩阵自身&#xff08;有点像一个两状态开关&#xff0c;在开与关之间来回切换&#xff09; 3. 对称矩阵的充要条件是矩阵转置一次后…

转置矩阵、对称矩阵、反对称矩阵以及向量的反对称矩阵

一、转置矩阵 假设矩阵 A 如下表示&#xff1a; 则其转置矩阵表示为&#xff1a; 二、对称矩阵 若矩阵 B 与其转置矩阵相等&#xff0c;则称矩阵 B 为对称矩阵&#xff0c;如&#xff1a; 三、反对称矩阵 若矩阵 C 与其转置矩阵取负后相等&#xff0c;则称矩阵 C 为反对称矩…

Java编程之转置矩阵

一、题目 利用随机函数产生36个10~30之间的整数给一个6*6的矩阵赋值。 &#xff08;1&#xff09;求最大元素&#xff0c;并指出其在矩阵中的所有出现位置&#xff1b; &#xff08;2&#xff09;求该矩阵的转置矩阵。 二、实验代码 package fighting; import java.util.Rand…

FPGA 矩阵转置

这里写目录标题 1 功能2 开发环境3 框架4 转置公式5 Simulation第一部分第二部分第三部分 6 Matlab代码产生FIFO数据产生转置矩阵 7 HDL仿真文件顶层文件FIFO顶层文件FIFO读FIFO写RAM顶层文件 8 IP配置FIFORAMROM 9 Reference 1 功能 通过tb读取本地数据保存到FIFO&#xff0c…

MATLAB的转置

小席的碎碎叨&#xff1a;   以前处理的数据通常都是实数矩阵&#xff0c;一直认为MATLAB中的转置可用实现&#xff0c;并没有发现有什么不对。但是&#xff0c;这段时间在做线性调频信号的干扰抑制的仿真&#xff0c;其信号矩阵都是复数矩阵&#xff0c;依然在需要转置的时候…

矩阵转置(transpose、T)

1.T T 适用于一、二维数组的转置 transpose 适用于高维数组&#xff0c;需要用到一个由轴编号组成的元组&#xff0c;才能进行转置 In [1]: import numpy as npIn [2]: arr np.arange(20).reshape(4,5)#生成一个4行5列的数组In [3]: arr Out[3]: array([[ 0, 1, 2, 3, 4]…

线性代数:转置矩阵(matrix transpose)和逆矩阵(matrix inverse)

这一篇是为了后面着色效果的数学基础做积累&#xff0c;之前我们使用矩阵的大部分情况都是直接的仿射空间变换&#xff0c;就是仿射空间A变换到仿射空间B&#xff0c;使用矩阵也都是如下&#xff1a; 矩阵T*齐次坐标V 齐次坐标V 其计算细节也就是矩阵行与向量列的点积&#xf…

转置矩阵(matrix transpose)和逆矩阵(matrix inverse)的相关公式

转载自: https://blog.csdn.net/yinhun2012/article/details/84236202 这一篇是为了后面着色效果的数学基础做积累&#xff0c;之前我们使用矩阵的大部分情况都是直接的仿射空间变换&#xff0c;就是仿射空间A变换到仿射空间B&#xff0c;使用矩阵也都是如下&#xff1a; 矩阵T…

转置矩阵(Transpose of a matrix)

定义 给定一个矩阵 A&#xff0c;将矩阵的行列互换得到的新矩阵称为转置矩阵&#xff0c;记为 &#xff0c;。转置矩阵的行列式不变&#xff0c;即 。转置矩阵由下列动作建立&#xff1a; 将 A 的横行写为 的纵列&#xff1b;将 A 的纵列写成 的横行。 形式来说&#xff0…