wsdl端口如何调用_如何学好网络编程--回答一个编程热爱者

目录

1 前言 1

2 原理 2

2.1 通信原理 2

3 IO模型 10

3.1 IO模型原理介绍及优势劣势分析 10

3.2 不同平台的差异 10

4 多线程模型 10

4.1 select+多线程 10

4.2 IOCP 10

4.3 epoll 10

4.4 reactor设计模式 10

4.5 preactor设计模式 10

5 协议 10

5.1 介绍 10

5.2 举例 10

6 服务器的关键技术高性能,高可用 10

7 学习方法分享 11

8 书籍推荐 11

linux socket内核源码实现:【Linux 内核网络协议栈源码剖析】socket.c--BSD Socket层(1)

前言

我虽然不是软件行业的编程大牛,但也是对编程事业十分热爱的群体成员之一,尤其是对网络编程情有独钟;经常被学弟们问到这个问题,有时候时间仓促没有说清楚怕反而耽误别人,于是我准备专门写一篇文章来回答这个问题,也算是对自己从业三年多的一个总结!知识有限,仅供参考!一次没写完,后期慢慢完善,纯个人经验,不按照专业体系来!愿对编程热爱的人永远保持热爱!

原理

通信原理

在没有网络通信的时候,各个电脑的软件都是各自为战,老死不相往来,那样的网络世界不能充分利用数据资源资源,极其枯燥乏味!

b80891701759d79094144c9c338f2668.png

上图是与世隔绝的计算机世界,没有网络,各个设备之间无法直接沟通;人们只能玩单机游戏,只能看自己电脑上存储的片,也不能及时沟通;于是蒂姆·伯纳斯·李苦思冥想就觉得应该建立网络这个东西,大家不同出门就可以相互沟通,可以共享各种信息,一起玩游戏;于是计算机世界就发生了天翻地覆的变化。

10f8363fd0d83ae29ffeabecf04b59ea.png

网络把世界上所有的设备连接在一起,从那时候起,人们就可以共享数据资源,一起玩游戏和及时沟通了;但这里有一个问题,大家都只想买个便宜的电脑,也不像购买太多的存储空间来存储数据,于是大家就上来出来了一个方法,我们应该把最浪费cpu的计算,大堆的数据存储放到公共的电脑上,于是就出现了服务这种东西。

e7bd5c76bea673a910c451d376d09dfc.png

服务器的出现使得整个互联网世界生活变得更加丰富多彩,这里的服务器包括服务器硬件和服务器程序;服务器硬件就是一个电脑主机,只是它的cpu、内存、磁盘、网卡等硬件配置都远高于一般的个人电脑的电脑,需要7x24小时的运行,肩负着为所有客户端程序提供服务的使命,而且大公无私地存储着所有用户需要的数据,硬件好一点情有可原。有了服务器,客户端就变爽了,只需要很垃圾的硬件配置,就可以在线观看互联网中的任何视频,和朋友们一起玩游戏,及时沟通。

网络中有那么多设备,我们如何精准地找到你心目中的她呢?我们人与人之间是用姓名或者身份证号来标识,而网络世界中我们用ip地址来唯一确定网络的设备;不过就算你找到你想连接的服务器设备,仍然无法正常沟通,因为服务器上运行着很多程序,服务器不知道你需要那个服务,于是你还需要指定服务端口;ip地址标记了互联网世界中的一台设备,而端口标记了一台设备中的唯一服务程序;反过来服务器需要给你答复,那么它也需要知道你(客户端)的ip地址和端口,如下图:

b1071c1ec24da2e06dc505eb363e6097.png

怎么来标识互联网中的唯一对话,那就一个网络全相关:本地ip,本地端口,远程ip,远程端口,通信协议。找到了互联网中的电脑,找到了电脑中运行的那个程序,还是不能正常通信,还需要大家都使用相同的协议;好比你打电话去咨询别人,然后前台帮你转接到了咨询目标,然后还需要大家都说中文(通信协议,比如tcp、udp、sctp)。百度百科对通信五元组的介绍:https://baike.baidu.com/item/%E4%BA%94%E5%85%83%E7%BB%84

说了那么多似乎跟网络编程无关的东西,接下来终于可以讲到怎么用socket编程来建立一个网络全相关了,然后进行正常的数据交互了。

24ee1d6579859af9cb1491da089519e2.png

服务器这边首先调用int socket(int domain,int type, int protocol)创建一个套接字句柄,比如是int sockfd = socket(int domain,int type, int protocol),这个接口会指定通信协议比如tcp;然后调用int bind(int sockfd,const struct sockaddr* myaddr,socklen_t addrlen)绑定本地ip(本机网卡)和端口(服务器进程标识),此时相当于建立了一个网络半相关,socket只标识了通信协议、本机ip、本机端口,因此还无法正常通信;然后就是调用int listen(int sockfd,int backlog)开启监听连接情况;再就是int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)接受客户端的连接,这个函数会返回一个新的socket句柄,int nclient = accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen),这个nclient是一个全相关,包括通信协议、本机ip、本机端口、远程ip、远程端口,通信协议、本机ip、本机端口是从监听套接字sockfd复制出来的,远程ip和远程端口是从连接中取得的,现在就可以正常通信了;调用ssize_t recv(int sockfd,void *buf, size_t len,int flags)就可以接收数据;调用ssize_t send(int sockfd,constvoid *buf, size_t len,int flags)就可以向对端发送数据;通信完成了就调用close把这个连接关闭;服务器工作还没完,这才完美服务完一个客户端的通信过程,还得继续监听其它客户端的连接,直到服务器关机。套接字接口的参考文章:https://blog.csdn.net/G_BrightBoy/article/details/12854117

客户端这边与服务器操作类似,只是不需要监听连接情况,也不需要一直运行。首先调用int socket(int domain,int type, int protocol)创建一个套接字句柄,比如是int sockfd = socket(int domain,int type, int protocol),这个接口会指定通信协议比如tcp;然后直接调用int connect(int sockfd,conststruct sockaddr *addr, socklen_t addrlen)连接到服务器,需要指定要连接服务器的ip和端口号,但是不需要指定本机的ip和端口号,ip操作系统会帮你绑定,端口号操作系统也会帮你随机分配一个;然后就是调用ssize_t recv(int sockfd,void *buf, size_t len,int flags)就可以接收数据;调用ssize_t send(int sockfd,constvoid *buf, size_t len,int flags)就可以向对端发送数据;通信完成了就调用close把这个连接关闭。

代码示例:https://blog.csdn.net/guo8113/article/details/26448011。

Server:

// server.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include <winsock2.h>

#include <iostream>

#include <string.h>

using namespace std;

#pragma comment(lib, "ws2_32.lib") //add ws2_32.lib

const int DEFAULT_PORT = 8000;

int main(int argc,char* argv[])

{

WORD wVersionRequested;

WSADATA wsaData;

int err,iLen;

wVersionRequested = MAKEWORD(2,2);//create 16bit data,网络动态库版本

//(1)Load WinSock,加载网络动态库

err = WSAStartup(wVersionRequested,&wsaData); //load win socket

if(err!=0)

{

cout<<"Load WinSock Failed!";

return -1;

}

//(2)create socket,准备连接全相关的内存资源

SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);

if(sockSrv == INVALID_SOCKET){

cout<<"socket() fail:"<<WSAGetLastError()<<endl;

return -2;

}

//(3)server IP,制定本机ip

SOCKADDR_IN addrSrv;

addrSrv.sin_family = AF_INET;

addrSrv.sin_addr.s_addr = htonl(INADDR_ANY);//Auto IP, byte sequence change

addrSrv.sin_port = htons(DEFAULT_PORT); //指定本机端口

//(4)bind,将ip和端口复制到套接字指向的内存块

err = bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

if(err!=0)

{

cout<<"bind()fail"<<WSAGetLastError()<<endl;

return -3;

}

//

//(5)listen,开启监听

err = listen(sockSrv,5);

if(err!=0)

{

cout<<"listen()fail"<<WSAGetLastError()<<endl;

return -4;

}

cout<<"Server waitting...:"<<endl;

//(6)client ip

SOCKADDR_IN addrClt;

int len = sizeof(SOCKADDR);

while(1)

{

//(7)accept,客户端连接进来,建立全相关连接了;也就是得到了远端ip和端口

SOCKET sockConn = accept(sockSrv,(SOCKADDR*)&addrClt,&len);

char sendBuf[1024],hostname[100];

if(gethostname(hostname,100)!=0) //get host name

strcpy(hostname,"None");

sprintf(sendBuf,"Welecome %s connected to %s!",inet_ntoa(addrClt.sin_addr),hostname);

//(8)send recv

err = send(sockConn,sendBuf,strlen(sendBuf)+1,0);

char recvBuf[1024]="0";

iLen = recv(sockConn,recvBuf,1024,0);

recvBuf[iLen]='0';

cout <<recvBuf<<endl;

//(9)close connected sock

closesocket(sockConn);

}

//(10)close server sock

closesocket(sockSrv);

//(11)clean up winsock

WSACleanup();

return 0;

}

客户端:

// client.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include <winsock2.h>

#include <iostream>

#include <string.h>

using namespace std;

#pragma comment(lib, "ws2_32.lib") //add ws2_32.lib

const int DEFAULT_PORT = 8000;

int main(int argc,char* argv[])

{

WORD wVersionRequested;

WSADATA wsaData;

int err,iLen;

wVersionRequested = MAKEWORD(2,2);//create 16bit data

//(1)Load WinSock

err = WSAStartup(wVersionRequested,&wsaData); //load win socket

if(err!=0)

{

cout<<"Load WinSock Failed!";

return -1;

}

//(2)create socket

SOCKET sockClt = socket(AF_INET,SOCK_STREAM,0);

if(sockClt == INVALID_SOCKET){

cout<<"socket() fail:"<<WSAGetLastError()<<endl;

return -2;

}

//(3)IP

SOCKADDR_IN addrSrv;

addrSrv.sin_family = AF_INET;

addrSrv.sin_addr.s_addr = inet_addr("127.0.0.1");

addrSrv.sin_port = htons(DEFAULT_PORT);

//(5)connect

err = connect(sockClt,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

if(err ==INVALID_SOCKET)

{

cout<<"connect() fail"<<WSAGetLastError()<<endl;

return -1;

}

char sendBuf[1024],hostname[100];

if(gethostname(hostname,100)!=0) //get host name

strcpy(hostname,"None");

strcpy(sendBuf,hostname);

strcat(sendBuf,"have connected to you!");

err = send(sockClt,sendBuf,strlen(sendBuf)+1,0);

char recvBuf[1024]="0";

iLen = recv(sockClt,recvBuf,1024,0);

if(iLen ==0)

return -3;

else if(iLen==SOCKET_ERROR){

cout<<"recv() fail:"<<WSAGetLastError()<<endl;

return -4;

}

else

{

recvBuf[iLen] = '0';

cout<<recvBuf<<endl;

}

closesocket(sockClt);

WSACleanup();

system("PAUSE");

return 0;

}

IO模型

IO模型原理介绍及优势劣势分析

不同平台的差异

多线程模型

select+多线程

IOCP

深入理解DMA技术原理:操作系统--I/O设备管理(1) - yaoxiaokui的专栏 - CSDN博客

异步IO实际上就是使用了DMA(direct memory access)技术;

DMA原理:DMA控制器直接将数据复制到内存中,复制完成之后才通知cpu干活;

中断技术原理:cpu提交任务给中断控制器,中断控制器将数据从磁盘复制到中断控制器缓存,然后中断控制器通知cpu来从缓存中把数据复制到用户内存;最坑的是循环IO模式;

中断和DAM使用了不同的控制器;DMA通知cpu干活的时机更加节约cpu,也更节约内存;

各个设备都有自己的寄存器,寄存器分为三类:数据寄存器、控制寄存器、状态寄存器;

epoll

reactor设计模式

preactor设计模式

协议

介绍

举例

TCP/IP协议

服务器的关键技术高性能,高可用

学习方法分享

先对网络编程有一定的概念,做一个简单的demo,不断网上面加功能;能到公司干活的水平了,再去看系统的书籍。

书籍推荐

《unix网络编程》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值