网络编程:套接字 socket
复习一下,先复习下简单的套接字。
好记性不如烂笔头,烂笔头不如烂键盘,烂键盘好过没键盘。
Windows下.........................................................................................................................
类型:
流式套接字(SOCK_STREAM):套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复送,并按顺序接收。TCP
数据报式套接字(SOCK_DGRAM):提供无连接服务,数据包以独立包形式发送,不提供无措保证,数据可能丢失或重复,并且接收顺序混乱。UDP
原始套接字(SOCK_RAW):原始套接字与流式和数据报套接字的区别在于:原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送的数据必须使用原始套接
常用基本函数:
- int WSAStartup(WORD,& WSADATA)
说明:加载套接字库,加载成功返回0。
参数一:指定套接字版本,高位指定主版本,低位指定副版本,可以利用MAKEWORD(x,y)生成,其中x是高位,y是低位。
参数二:用于接收WSAStartup加载的套接字库版本信息。WSADATA结构体中,第一个成员代表主版本,第二个成员代表副版本。
- int socket(int af, int type, int protocol)
说明:创建套接字。成功返回套接字描述符。失败返回INVALID_SOCKET。
参数一:指定地址族,对于TCP/IP协议 ,只能为AF_INET也可以写为PF_INET.
参数二:指定套接字类型,SOCK_STREAM为流式套接字(TCP),SOCK_DGRAM产生数据报套接字(UDP)。
参数三:指定与地址家族相关的协议,如果为0会自动分配一个合适的协议。
- int bind( SOCKET sockaddr, const struct sockaddr FAR* my_addr,int addrlen)
说明:为套接字绑定本地地址,成功返回0,失败返回-1
参数一:通过socket()函数创建的套接字
参数二:指定的本地地址信息,类型为sockaddr结构指针变量
参数三:指定地址结构的长度,sizeof(sockaddr)
struct sockaddr {unsigned short sa_family; //指定地址族,必须为AF_INETchar sa_data[14]; //占位,指定协议相关具体地址信息};
为了方便地址填写,一般用sockaddr_in代替sockaddr,参数填写的时候进行强转即可
struct sockaddr_in {short int sin_family; //地址族 只能是AF_INETunsigned short int sin_port; //指定端口号(要网字节序 使用函数htons()转化)struct in_addr sin_addr; //套接字主机IP地址,用到in_addr结构体unsigned char sin_zero[8]; //填充数,使sockaddr_in和sockaddr的sizeof相等};
对于IP地址,如果指定为INADDR_ANY,则允许套接字向任何分配给本机机器的IP地址发送或接受数据,如果机器有多个网卡,可以简化应用程序的编写。
typedef struct in_addr {union {struct{ unsigned char s_b1,s_b2, s_b3,s_b4;} S_un_b;struct{ unsigned short s_w1, s_w2;} S_un_w;unsigned long S_addr; // IP地址(网络字节序,利用htonl()转换)} S_un;} IN_ADDR;
inet_addr(“192.168.1.156”)会返回一个适合S_addr 的unsigned long类型,inet_ntoa(in_addr)则相反 ,会将一个in_addr结构体返回一个点分的字符串,”192.168.1.156”
- int listen(int sockfd, int backlog)
说明:将套接字设置为监听模式,成功返回0,失败返回-1
参数一:套接字描述符socket()函数创建的套接字
参数而:等待连接队列的最大长度(并不是在一个端口连接数)
- accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
说明:等待客户连接,并接受客户连接。请求成功,返回一个相对于连接的新的套接字,原先的套接字,继续监听连接请求,失败返回INVALID_SOCKET
参数一:套接字描述符
参数二:保存发起连接的套接字的IP和端口信息,也利用sockaddr_in代替sockaddr
参数三:保存返回的套接字地址长度,必须要赋初值,sizeof(sockaddr)
- int connect (SOCKET s, const struct sockaddr * name, int namelen )
说明:与指定套接字建立连接,成功返回0,失败返回SOCKET_ERROR,也就是-1.
参数一:套接字描述符
参数二:指定要连接的套接字的地址,也就是服务端的
参数三:地址长度
- int send(SOCKET s, const char FAR *buf, int len, int flags) / sendto
说明:向指定套接字发送数据,send用于TCP连接,sento用于UDP连接,并且sendto多了两个参数,用来指定服务端的地址和长度。成功返回发送数据长度,失败返回SOCKET_ERROR
参数一:指定接收端套接字,即通过accept()接受的套接字
参数二:要发送的字符数据
参数三:带发送数据的长度
参数四:执行方式,影响send的调用行为,一般设为0
- int recv(SOCKET s, char FAR *buf, int len, int flags) / recvfrom
说明:接收指定套接字数据,recv用于TCP连接,recvfrom用于UDP连接,并且recvfrom多了两个参数,用来指定服务端的地址和长度,并且接收地址长度的参数必须初始化。成功返回接收数据长度,失败返回-1
参数一:指定接收端的套接字
参数二:存储数据的缓冲区
参数三:缓冲区大小
参数四:执行方式
- closesocket(socket)
说明:关闭套接字
- WSACleanup()
说明:终止对套接字库的使用
- int WSAGetLastError() / GetLastError()
说明:返回一个int类型的Winsock错误代码,对于上述函数执行返回失败,都可以利用该函数进行捕捉错误。
TCP和UDP连接:
TCP:面向连接的,可靠的
(1)数据传输过程必须经过建立连接、维护连接和释放连接3个阶段
(2)在传输过程中,不需要携带目的主机的地址
(3)可靠,协议复杂,通信效率不低
UDP:面向无连接的,不可靠
(1)不需要连接
(2)每个分组都携带完整的目的主机地址,在系统中独立传送
(3)没有顺序控制,接收方的分组可能出现乱序、重复和丢失现象
(4)通信效率高,不可靠
TCP例子:
图片 哪儿来的?
服务端:
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<winsock2.h>
using namespace std;int main()
{WORD word = MAKEWORD(2, 0);WSADATA wsaData;if (WSAStartup(word, &wsaData) != 0){printf("套接字库加载失败!\n");int err = GetLastError();printf("errNum = %d\n", err);return -1;}if (LOBYTE(wsaData.wVersion != 2) || HIBYTE(wsaData.wHighVersion != 0)){printf("套接字库加载失败!\n");WSACleanup();return -1;}int sockSrv = socket(AF_INET, SOCK_STREAM, 0);if (sockSrv == INVALID_SOCKET){printf("套接字创建失败!\n");int err = GetLastError();printf("errNum = %d\n", err);WSACleanup();return -1;}sockaddr_in addrSrv;addrSrv.sin_family = AF_INET;addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);addrSrv.sin_port = htons(6666);if (int res = bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR))!= 0){printf("套接字绑定失败!");int err = GetLastError();printf("errNum = %d\n", err);WSACleanup();return -1;}if (int res = listen(sockSrv, 5) != 0){printf("监听套接字失败!");int err = GetLastError();printf("errNum = %d\n", err);WSACleanup();return -1;}sockaddr_in addrClient;int addrlen;while (1){addrlen = sizeof(SOCKADDR);int sockClient = accept(sockSrv, (SOCKADDR*)&addrClient, &addrlen);if (sockClient == INVALID_SOCKET){printf("套接字连接失败!");int err = GetLastError();printf("errNum = %d\n", err);continue;}char sendBuf[200] = { 0 };char recvBuf[200] = { 0 };sprintf(sendBuf, "hello ,this is %s", inet_ntoa(addrSrv.sin_addr));send(sockClient, sendBuf, strlen(sendBuf) + 1, 0);recv(sockClient, recvBuf, sizeof(recvBuf), 0);printf("%s\n", recvBuf);closesocket(sockClient);}closesocket(sockSrv);WSACleanup();system("pause");return 0;
}
客户端:
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<winsock2.h>
using namespace std;int main()
{WORD word = MAKEWORD(2, 0);WSADATA wsaData;if (WSAStartup(word, &wsaData) != 0){printf("套接字库加载失败!\n");int err = GetLastError();printf("errNum = %d\n", err);return -1;}if (LOBYTE(wsaData.wVersion != 2) || HIBYTE(wsaData.wHighVersion != 0)){printf("套接字库加载失败!\n");WSACleanup();return -1;}int sockClient = socket(AF_INET, SOCK_STREAM, 0);if (sockClient == INVALID_SOCKET){printf("套接字创建失败!\n");int err = GetLastError();printf("errNum = %d\n", err);WSACleanup();return -1;}sockaddr_in addrSrv;addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(6666);if (connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) != 0){printf("套接字连接失败!\n");int err = GetLastError();printf("errNum = %d\n", err);WSACleanup();return -1;}char recvBuf[200] = { 0 };char sendBuf[200] = { 0 };int recvLen = recv(sockClient, recvBuf, sizeof(recvBuf), 0);printf("%s\n",recvBuf);sprintf(sendBuf," my name is zhangsan");send(sockClient,sendBuf,strlen(sendBuf)+1,0);closesocket(sockClient);WSACleanup();system("pause");return 0;
}
UDP例子:
服务端:
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<winsock2.h>
using namespace std;int main()
{WORD word = MAKEWORD(2, 0);WSADATA wsaData;if (WSAStartup(word, &wsaData) != 0){printf("套接字库加载失败!\n");int err = GetLastError();printf("errNum = %d\n", err);return -1;}if (LOBYTE(wsaData.wVersion != 2) || HIBYTE(wsaData.wHighVersion != 0)){printf("套接字库加载失败!\n");return -1;WSACleanup();}int sockSrv = socket(AF_INET, SOCK_DGRAM, 0);if (sockSrv == INVALID_SOCKET){printf("创建套接字失败!\n");int err = GetLastError();printf("errNum = %d\n", err);WSACleanup();return -1;}sockaddr_in addrSrv;addrSrv.sin_family = AF_INET;addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);addrSrv.sin_port = htons(6000);if (bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) != 0){printf("套接字绑定失败!\n");int err = GetLastError();printf("errNum = %d\n", err);WSACleanup();return -1;}sockaddr_in addrClient;int addrlen = sizeof(SOCKADDR);while (1){char sendBuf[200] = { 0 };char recvBuf[200] = { 0 };int recvLen = recvfrom(sockSrv, recvBuf, sizeof(recvBuf), 0, (SOCKADDR*)&addrClient, &addrlen);if (recvLen > 0){printf("%s\n", recvBuf);}sprintf(sendBuf, "hello ,this is %s", inet_ntoa(addrSrv.sin_addr));sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrClient, addrlen);}closesocket(sockSrv);WSACleanup();system("pause");return 0;
}
客户端:
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<winsock2.h>
using namespace std;int main()
{WORD word = MAKEWORD(2, 0);WSADATA wsaData;if (WSAStartup(word, &wsaData) != 0){printf("套接字库加载失败!\n");int err = GetLastError();printf("errNum = %d\n", err);return -1;}if (LOBYTE(wsaData.wVersion != 2) || HIBYTE(wsaData.wHighVersion != 0)){printf("套接字库加载失败!\n");return -1;WSACleanup();}int sockClient = socket(AF_INET, SOCK_DGRAM, 0);if (sockClient == INVALID_SOCKET){printf("创建套接字失败!\n");int err = GetLastError();printf("errNum = %d\n", err);WSACleanup();return -1;}sockaddr_in addrSrv;addrSrv.sin_family = AF_INET;addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");addrSrv.sin_port = htons(6000);int addrlen = sizeof(SOCKADDR);char sendBuf[200] = { 0 };char recvBuf[200] = { 0 };sprintf(sendBuf, "my name is demaxiya", inet_ntoa(addrSrv.sin_addr));sendto(sockClient, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrSrv, addrlen);int recvLen = recvfrom(sockClient, recvBuf, sizeof(recvBuf), 0,(SOCKADDR*)&addrSrv, &addrlen);if (recvLen > 0){printf("%s\n", recvBuf);}closesocket(sockClient);WSACleanup();system("pause");return 0;
}
错误不知道有没有,有也别慌。
网络编程:套接字 socket相关推荐
- 网络编程套接字Socket
首先理解源IP地址和目的IP地址 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址 了解端口号 端口号(port)是传输层协议的内容 端口号是一个32位的整数 端口号用来标 ...
- 网络编程套接字(四)
网络编程套接字(四) 文章目录 网络编程套接字(四) 一.实现tcp服务器多用户版本(多进程.多线程.线程池版本) 一.实现tcp服务器多用户版本(多进程.多线程.线程池版本) tcp_process ...
- 网络编程套接字(三)
网络编程套接字(三) 文章目录 网络编程套接字(三) 一.实现简单的Tcp服务器(单用户) 一.实现简单的Tcp服务器(单用户) tcp_socket.hpp #pragma once #includ ...
- 网络编程套接字(二)
网络编程套接字(二) 文章目录 网络编程套接字(二) 一.简单的UDP网络程序 一.简单的UDP网络程序 封装udp_socket #pragma once #include <cstdio&g ...
- 网络编程套接字(一)
网络编程套接字(一) 文章目录 网络编程套接字(一) 一.基础知识 二.sock编程接口 一.基础知识 1. 理解源IP地址和目的IP地址 在IP数据包头部中,有两个IP地址,分别叫源IP地址和目的I ...
- 详细讲解 —— 网络编程套接字(Java EE初阶)
网络编程套接字 1 认识网络编程套接字 2 UDP 数据报套接字编程 2.1 UPD服务端 2.1 UDP客户端 2.3 结果测试 3 TCP流套接字编程 3.1 TCP服务端 3.2 TCP客户端 ...
- 【javaEE】网络编程套接字
To u&me: 努力经营当下,直至未来明朗 文章目录 前言 一.网络编程(没时间可以跳过) 一)网络编程了解 二)相关基本概念 二.Socket套接字 三.数据报套接字通信(UDP) 写一个 ...
- Java网络编程套接字
文章目录 1.网络编程基础 2.什么是网络编程 3.网络编程中的基本概念 3.1.发送端和接收端 3.2 请求和响应 3.3 客户端和服务端 3.4 常见的客户端服务端模型 4.Socket套接字 4 ...
- UNIX网络编程---套接字编程简介(三)
UNIX网络编程---套接字编程简介 一.概述 从这里开始正式开始网络编程之旅,所有的函数都是基本的库函数.这些都是网络编程的基础.Come on!!!! 二.套接字地址结构 大多数套接字函数都需要一 ...
- 【网络编程套接字(一)】
网络编程套接字(一) 理解源IP地址和目的IP地址 理解源MAC地址和目的MAC地址 理解源端口号和目的端口号 PORT VS PID 认识TCP协议和UDP协议 网络字节序 socket编程接口 s ...
最新文章
- Jsoncpp 使用方法解析
- 声腔设计中无前腔的影响
- python装饰器的顺序_python中多个装饰器的执行顺序详解
- C语言中printf输出特殊字符(“%d“或者“\n“)
- 作业6--第3、4、5天进度
- js中的var和new
- jnid中mysql的驱动类_JDBC与JNDI的区别
- 2022山东理工大学pta程序设计---实验四1---13题解
- [Matlab]绘图颜色
- 团队协作工具-版本控制软件SVN、Git、码云
- stm32指纹考勤机 (程序源码包括app程序+pcb电路图+原件清单)
- CK11N改标准价格
- iOS编译cURL库并链接darwinssl,zlib,c-ares库操作步骤
- win10最简单定时关机命令
- 计算机应用基础试题文件夹,计算机应用基础试题及参考答案
- 软件工程 - 项目管理
- javascript面向对象(三):class语法详解
- VHDL中的signal(信号)variable(变量)的定义与赋值
- 计算机毕设Python+Vue智能仓储进出货管理系统(程序+LW+部署)
- 中兴面试-guozhijun20160628
热门文章
- 曙光服务器进去系统后黑屏,大明:电脑进入win7系统后黑屏的解决办法
- “红遍全球”的恶意软件 Mirai 换了个新马甲,这次瞄上我国2亿多台IoT设备
- Ci521 13.56MHz非接触式读写器芯片(AB卡,低成本)
- 手机电池充电时间计算方法
- 4 种在 Linux 中检查默认网关或者路由器 IP 地址的方法
- 中国香港DHB Global公司首席执行官道格拉斯•科利: 大数据是一个历史性机遇...
- 天猫数据分析软件(天猫销售数据如何查询)
- 2020年月份间销售额波动原因定位
- [深入研究4G/5G/6G专题-60]: Nokia如何让小基站即插即用
- ES8323S双通道DAC单通道ADC可单声道录音多路选择