IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> socket网络编程(c++) -> 正文阅读

[C++知识库]socket网络编程(c++)


前言

本文内容分两个部分: socket编程基础知识 与 简单实例。

提示:阅读前有一定计算机网络知识的基础

一、基础知识

1.Internet套接字

【介绍】
应用层 与 传输层 的通道,由ip地址 + 端口号
【分类】
流格式(stream sockets)
sock_stream: 全双工可靠面向连接的传输,tcp
数据包格式(datagram socket)
sock_dgram: 无连接传输,速度更快,udp

2.socket相关结构体

  1. socket描述符:int类型
    注意:网络字节顺序(Network Byte Order)与 本机字节顺序(Host Byte Order)
  2. struct sockaddr:
struct sockaddr {
  unsigned short sa_family; //协议族
  char sa_data[14]; //协议地址
};
  1. struct sockaddr_in:与sockaddr等价,常用
struct sockaddr_in {
  short int sin_family; //通信类型
  unsigned short int sin_port; //端口
  struct in_addr sin_addr; //ip
  unsigned char sin_zero[8]; //同sockaddr长度相同
};
  1. struct in_addr:
struct in_addr {
  unsigned long s_addr;
};
  1. 本机转换
    n:网络顺序,h:本机顺序,s:short,l:long
    htons()–“Host to Network Short”
    htonl()–“Host to Network Long”
    ntohs()–“Network to Host Short”
    ntohl()–“Network to Host Long”
    注:
    本机字节顺序:与cpu架构有关,x86为小端序
    网络字节顺序:大端序
  2. ip地址类型转换
    p or a:表达形式(ascii字符串)
    n:数值形式(二进制数–存在struct in_addr中)
/*1.字符串转化为数值 inet_addr()
注:input=255.255.255.255,output=-1*/
ina.sin_addr.s_addr = inet_addr("132.241.5.10");
/*2.地址形式转化为字符串 ntoa()
注:每次调用会覆盖上次调用*/
printf("%s",inet_ntoa(ina.sin_addr));
/*3.新型转化函数:兼容ipv4,ipv6
*/
int inet_pton(int family, const char *strptr, void *addrptr);    
//将表达形式(字符串)转化为数值格式(结构体)
//返回值:若成功则为1,若输入不是有效的表达式则为0,若出错则为-1
 
const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);     
//将数值格式(结构体)转化为表达形式(字符串)
//返回值:若成功则为指向结构的指针,若出错则为NULL

3. server&client交互过程

1.socket 函数 : 创建套接字
int socket(int domain, int type, int protocol)
domain : PF_INET, PF_INET6
type : SOCK_STREAM, SOCK_DGRAM
protocol : IPPROTO_TCP, IPPROTO_UDP

2.bind 函数 : 绑定(ip地址,端口号), 服务端使用
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
sockfd : 服务器socket
addr : 服务器地址

3.listen 函数 : 服务端监听socket,等待连接
int listen(int sockfd, int backlog)
sockfd : 服务器socket
backlog : 排队队列

4.connect 函数 : 客户端发送的连接请求
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd : 客户端socket
addr : 服务器地址

5.accept函数 : 服务器监听发现请求,接收
int accept(int sockfd, struct sockaddr *addr, socklen_t addrlen)
sockfd : 服务器socket
addr : 客户端地址
注:服务端socket: 监听socket、连接socket
监听socket:服务器生命周期仅创建一个
连接socket:每次accept返回新套接字

二、简单实例

【server】
注:链接时添加-lws2_32

#include<winsock2.h>
#include<iostream>
#include<string>

using namespace std;
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char* argv[])
{
	//初始化DLL, 调用winsock2.2 
    WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsdata;
    if (WSAStartup(sockVersion, &wsdata) != 0)
    {
        return 1;
    }
    
	//创建套接字描述符 
    SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listen_sock == -1)
    {
        cout << "error: create server listen_socket" << endl;
        return 1;
    }
    
    sockaddr_in sockAddr;
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons(8888);
    sockAddr.sin_addr.s_addr = INADDR_ANY;
    
    //绑定sockaddr_in 到套接字描述符 
	if (bind(listen_sock, (sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR){
        cout << "error: bind" << endl;
        return 1;
    }
    
    //listen
    if(listen(listen_sock, 5) == -1)
	{
		cout << "Error: listen" << endl;
        return 1;
	}
	
	SOCKET connect_sock;
    sockaddr_in client_sin;
    char msg[100]; //存储传送的消息
    int flag = 0; //是否已经连接上
    int len = sizeof(client_sin);
    
    while (true){
        //创建连接socket  
		if(!flag)
            cout << "listening..." << endl;   
        connect_sock = accept(listen_sock, (sockaddr*)&client_sin, &len);
        if (connect_sock == -1)
		{
            cout << "error:accept" << endl;
            flag = 0;
            return 1;
        }
        if(!flag)
            cout << "connected:" << inet_ntoa(client_sin.sin_addr) << endl;
        //连接成功 
		flag = 1;
		
		//服务器recv 
        int num = recv(connect_sock, msg, 100, 0);
        if (num > 0)
        {
            msg[num] = '\0';
            cout <<"Client say: "<< msg << endl;
        
		}
        //服务器send 
        string data;
        getline(cin, data);
        const char * sendData;
        sendData = data.c_str();
        send(connect_sock, sendData, strlen(sendData), 0);
        
        //关闭连接 
        closesocket(connect_sock);
    }
    closesocket(listen_sock);
    WSACleanup();

    return 0;
}

【client】

#include<winsock2.h>
#include<iostream>
#include<string>
using namespace std;
#pragma comment(lib, "ws2_32.lib")

int main()
{
    WORD sockVersion = MAKEWORD(2, 2);
    WSADATA data;
    if (WSAStartup(sockVersion, &data) != 0)
    {
        return 1;
    }

    while (true){
    	
    	//创建套接字描述符 
        SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (clientSocket == INVALID_SOCKET){
            cout << "Socket error" << endl;
            return 1;
        }
        sockaddr_in sock_in;
        sock_in.sin_family = AF_INET;
        sock_in.sin_port = htons(8888);
        sock_in.sin_addr.s_addr = inet_addr("127.0.0.1");
        
        //connect 
        if (connect(clientSocket, (sockaddr*)&sock_in, sizeof(sock_in) )== SOCKET_ERROR){
            cout << "Connect error" << endl;
            return 1;
        }
        
        //send 
      	string data;
        getline(cin, data);
        const char * msg;
        msg = data.c_str();
        send(clientSocket, msg, strlen(msg), 0);

		//recv 
        char revdata[100];
        int num = recv(clientSocket, revdata, 100, 0);
        if (num > 0){
            revdata[num] = '\0';
            cout <<"Sever say:"<< revdata << endl;
        }
        closesocket(clientSocket);

    }

    WSACleanup();

    return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-16 19:28:07  更:2021-10-16 19:28:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 20:02:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计