常见的网络编程
分为七层网络架构:应用层、表示层、会话层、传输层、网络层、数据连接层、物理层
五层网络结构:应用层、传输层、网络层、数据连接层、物理层
socket 套接字(IP地址、端口号)
tcp/ip 协议簇
ipv4 (32位) ipv6(64位)
ip地址分类:
A类: 0 网络号(7位) 主机号(24位)
B类: 10 网络号(14位) 主机号(16位)
C类: 110 网络号(21位) 主机号(8位)
tcp 通信模型
一、三次握手
服务器和客户端需要建立一种稳定的传输管道,需要3个步骤
1、由客户端向服务器端发送信息,发一个报文(message syn)
2、服务器把刚刚接收到的客户端的报文重新发回去,再发一个报文(ack)
3、客户端在向服务器端发送报文(ack)
二、四次挥手
断开稳定的传输通需要四个步骤
1、客户端向服务器端,发送fin(结束标记)
2、服务器收到fin,它会发回一个ack
3、服务器关闭客户端的链接
4、客户端发回ack确认
TCP模型
C(客户端)/S(服务器)模型 一对一的关系
1、准备工作
2、确认版本信息 ,要确认socket的版本 ipv4
3、创建套接字 (socket)
4、初始化协议地址
5、绑定(s)
6、监听(s)
7、接收连接(s) 客户端需要连接服务器©
8、连接完成,开始通信
9、关闭socket
接收
#include "stdafx.h"
//1、准备工作
#include< Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
void color(const unsigned short color1)
{
if (color1 >= 0 && color1 <= 15)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color1);
else
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
int _tmain(int argc, _TCHAR* argv[])
{
color(15);
//2、确认版本信息
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){
printf("请求版本失败,启动不成功\n");
return -1;
}
printf("请求版本成功\n");
//3、创建套接字 (socket)
/*第一个参数协议:协议决定了socket的地址类型,在通信中必须采用对应的协议
AF_INET,决定了用ipv4地址(32位)与端口号(16位)的组合
第二个参数是类型,SOCK_STREAM(流式)
//第三个参数是决定用tcp还是udp的传输协议 IPPROTO_TCP代表TCP
*/
SOCKET serverSocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == serverSocket){
printf("创建套接字失败\n");
WSACleanup();
return -1;
}
printf("创建套接字成功\n");
//4、初始化协议地址
SOCKADDR_IN serverAddr = {};
//指定协议簇,需要和第三部的第一个参数一致
serverAddr.sin_family = AF_INET;
//指定端口号
serverAddr.sin_port = htons(8080);
//指定ip地址
/*inet_addr()是将一个点分十进制的ip地址转换成一个长整数类型*/
serverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//INADDR_ANY 表示不确定地址 任意地址只要能找到端口号就能用
//serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;
//5、绑定(s)
int s=bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));
if (s == SOCKET_ERROR){
printf("绑定失败\n");
closesocket(serverSocket);
WSACleanup();
return -1;
}
printf("绑定成功\n");
//6、监听(s)
//listen(serverSocket, 10);
if (SOCKET_ERROR ==listen(serverSocket, 10))
{
printf("监听失败\n");
closesocket(serverSocket);
WSACleanup();
return -1;
}
printf("监听成功\n");
//7、接收连接(s)
SOCKADDR_IN clientAddr = {};
int len = sizeof(clientAddr);
SOCKET clientSocket=accept(serverSocket, (sockaddr*)(&clientAddr), &len);
if (clientSocket == INVALID_SOCKET)
{
printf("连接失败\n");
closesocket(serverSocket);
WSACleanup();
return -1;
}
printf("连接成功,客户端的ip: %s\n请等待...\n\n", inet_ntoa(clientAddr.sin_addr));
//8、连接完成,开始通信
char buff[128] = {};
int bufflen = 0;
char clientBuff[128] = {};
while (1)
{
memset(buff, 0, sizeof(buff));
bufflen=recv(clientSocket, buff, sizeof(buff)-1, 0);
color(6);
if (bufflen > 0){
printf("接收的内容: %s\n", buff);
}
memset(clientBuff, 0, sizeof(clientBuff));
color(15);
printf("请输入: ");
scanf_s("%s", clientBuff, sizeof(clientBuff)-1);
bufflen = send(clientSocket, clientBuff, sizeof(clientBuff)-1, 0);
if (bufflen > 0){
printf("发送成功,请等待...\n");
}
}
//9、关闭socket
closesocket(clientSocket);
closesocket(serverSocket);
WSACleanup();
return 0;
}
发送
#include "stdafx.h"
#include <stdio.h>
//1、准备工作
#include< Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
void color(const unsigned short color1)
{
if (color1 >= 0 && color1 <= 15)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color1);
else
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
int _tmain(int argc, _TCHAR* argv[])
{
color(15);
//2、确认版本信息
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){
printf("请求版本失败,启动不成功\n");
return -1;
}
printf("请求版本成功\n");
//3、创建套接字 (socket)
/*第一个参数协议:协议决定了socket的地址类型,在通信中必须采用对应的协议
AF_INET,决定了用ipv4地址(32位)与端口号(16位)的组合
第二个参数是类型,SOCK_STREAM(流式)
//第三个参数是决定用tcp还是udp的传输协议 IPPROTO_TCP代表TCP
*/
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == clientSocket){
printf("创建套接字失败\n");
WSACleanup();
return -1;
}
printf("创建套接字成功\n");
//4、初始化协议地址
SOCKADDR_IN clientAddr = {0};
//指定协议簇,需要和第三部的第一个参数一致
clientAddr.sin_family = AF_INET;
//指定端口号
int b;
printf("输入端口号:");
scanf("%d", &b);
clientAddr.sin_port = htons(b);
//指定ip地址
/*inet_addr()是将一个点分十进制的ip地址转换成一个长整数类型112.74.89.58 :35063*/
char a[20];
printf("输入地址:");
scanf("%s", a);
clientAddr.sin_addr.S_un.S_addr = inet_addr(a);
//INADDR_ANY 表示不确定地址 任意地址只要能找到端口号就能用
//clientAddr.sin_addr.S_un.S_addr = INADDR_ANY;
//5、客户端需要连接服务器(c)
if (SOCKET_ERROR == connect(clientSocket, (sockaddr *)&clientAddr, sizeof(clientAddr)))
{
printf("连接失败\n");
WSACleanup();
closesocket(clientSocket);
return -1;
}
printf("连接成功\n\n\n");
//6、连接完成,开始通信
char buff[128] = {};
int bufflen = 0;
char clientBuff[128] = {};
while (1)
{
memset(buff, 0, sizeof(buff));
color(15);
printf("请输入: ");
scanf_s("%s", buff, sizeof(buff)-1);
bufflen = send(clientSocket, buff, sizeof(buff)-1, 0);
if (bufflen > 0){
printf("发送成功,请等待...\n");
}
memset(clientBuff, 0, sizeof(clientBuff));
bufflen = recv(clientSocket, clientBuff, sizeof(clientBuff)-1, 0);
color(6);
if (bufflen > 0){
printf("接收的内容: %s\n", clientBuff);
}
}
//7、关闭socket
closesocket(clientSocket);
WSACleanup();
return 0;
}