热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

网络编程Tcp的客户端和服务器端

本文首先对基础知识做一下介绍,后面会给出示例程序,便于分析理解。大部分资料来源于网络,自己只是对其做了个整理。首先我们先来回顾下网络模型1

本文首先对基础知识做一下介绍,后面会给出示例程序,便于分析理解。大部分资料来源于网络,自己只是对其做了个整理。

 

    首先我们先来回顾下网络模型

    1. ISO(internet Standard Organization 国际标准组织)对OSI(Open SYstem Interconnect开放互联

模型) 七层网络模型的定义:
物理层(Physical layer) 链路层(Data link layer) 网络层(Network layer) 
传输层(Transport layer) 会话层(Session layer) 表示层(Presentation layer) 

应用层(Application layer)
    2. TCP/IP模型分为四层:
  网络接口层(Network access layer), 互联网层(internet layer),传输层((Transport layer),

  和应用层(Application layer).

 

   实际中我们应用的是TCP/IP网络模型,而接下来讨论的windows socket 也是基于本模型的。所以有必要

先了解下TCP/IP 体系结构与特点。

 

TCP/IP 体系结构与特点

1、TCP/IP体系结构


TCP/IP协议实际上就是在物理网上的一组完整的网络协议。其中TCP是提供传输层服务,而IP则是提供网络层服务。TCP/IP包括以下协议:(结构如图1.1)
[网络编程] <wbr>socket <wbr>编程浅谈&#xff08;一&#xff09;
(图1.1)

IP&#xff1a; 网间协议(Internet Protocol) 负责主机间数据的路由和网络上数据的存储。同时为ICMP&#xff0c;TCP&#xff0c;UDP提供分组发送服务。用户进程通常不需要涉及这一层。
ARP&#xff1a; 地址解析协议(Address Resolution Protocol)
此协议将网络地址映射到硬件地址。
RARP&#xff1a; 反向地址解析协议(Reverse Address Resolution Protocol)
此协议将硬件地址映射到网络地址
ICMP&#xff1a; 网间报文控制协议(Internet Control Message Protocol)
此协议处理信关和主机的差错和传送控制。
TCP&#xff1a; 传送控制协议(Transmission Control Protocol)
这是一种提供给用户进程的可靠的全双工字节流面向连接的协议。它要为用户进程提供虚电路服务&#xff0c;并为数据可靠传输建立检查。&#xff08;注&#xff1a;大多数网络用户程序使用TCP&#xff09;
UDP&#xff1a; 用户数据报协议(User Datagram Protocol)
这是提供给用户进程的无连接协议&#xff0c;用于传送数据而不执行正确性检查。
FTP&#xff1a; 文件传输协议(File Transfer Protocol)
允许用户以文件操作的方式&#xff08;文件的增、删、改、查、传送等&#xff09;与另一主机相互通信。
SMTP&#xff1a; 简单邮件传送协议(Simple Mail Transfer Protocol)
SMTP协议为系统之间传送电子邮件。
TELNET&#xff1a;终端协议(Telnet Terminal Procotol)
允许用户以虚终端方式访问远程主机
HTTP&#xff1a; 超文本传输协议(Hypertext Transfer Procotol)
TFTP: 简单文件传输协议(Trivial File Transfer Protocol)

2、TCP/IP特点
TCP/IP协议的核心部分是传输层协议(TCP、UDP)&#xff0c;网络层协议(IP)和物理接口层&#xff0c;这三层通常是在操作系统内核中实现。因此用户一般不涉及。编程时&#xff0c;编程界面有两种形式&#xff1a;一、是由内核心直接提供的系统调用&#xff1b;二、使用以库函数方式提供的各种函数。前者为核内实现&#xff0c;后者为核外实现。用户服务要通过核外的应用程序才能实现&#xff0c;所以要使用套接字(socket)来实现。
图1.2是TCP/IP协议核心与应用程序关系图。
[网络编程] <wbr>socket <wbr>编程浅谈&#xff08;一&#xff09;
(图1.2)

 

涉及到的专用术语
1、套接字
它是网络的基本构件。它是可以被命名和寻址的通信端点&#xff0c;使用中的每一个套接字都有其类型和一个与之相连听进程。套接字存在通信区域&#xff08;通信区域又称地址簇&#xff09;中。套接字只与同一区域中的套接字交换数据&#xff08;跨区域时&#xff0c;需要执行某和转换进程才能实现&#xff09;。WINDOWS 中的套接字只支持一个域——网际域。套接字具有类型。
WINDOWS SOCKET 1.1 版本支持两种套接字&#xff1a;流套接字(SOCK_STREAM)和数据报套接字(SOCK_DGRAM)

2、WINDOWS SOCKETS 实现
一个WINDOWS SOCKETS 实现是指实现了WINDOWS SOCKETS规范所描述的全部功能的一套软件。一般通过DLL文件来实现

3、阻塞处理例程
阻塞处理例程(blocking hook,阻塞钩子)是WINDOWS SOCKETS实现为了支持阻塞套接字函数调用而提供的一种机制。

4、多址广播&#xff08;multicast&#xff0c;多点传送或组播&#xff09;
是一种一对多的传输方式&#xff0c;传输发起者通过一次传输就将信息传送到一组接收者&#xff0c;与单点传送
(unicast)和广播(Broadcast)相对应。

 

客户机/服务器模式
在TCP/IP网络中两个进程间的相互作用的主机模式是客户机/服务器模式(Client/Server model)。该模式的建立基于以下两点&#xff1a;1、非对等作用&#xff1b;2、通信完全是异步的。客户机/服务器模式在操作过程中采取的是主动请示方式&#xff1a;

首先服务器方要先启动&#xff0c;并根据请示提供相应服务&#xff1a;&#xff08;过程如下&#xff09;
1、打开一通信通道并告知本地主机&#xff0c;它愿意在某一个公认地址上接收客户请求。
2、等待客户请求到达该端口。
3、接收到重复服务请求&#xff0c;处理该请求并发送应答信号。
4、返回第二步&#xff0c;等待另一客户请求
5、关闭服务器。
客户方&#xff1a;
1、打开一通信通道&#xff0c;并连接到服务器所在主机的特定端口。
2、向服务器发送服务请求报文&#xff0c;等待并接收应答&#xff1b;继续提出请求……
3、请求结束后关闭通信通道并终止。

 

基本套接字函数

1、创建套接字——socket()
功能&#xff1a;使用前创建一个新的套接字
格式&#xff1a;SOCKET PASCAL FAR socket(int af,int type,int procotol);
参数&#xff1a;af: 通信发生的区域
type: 要建立的套接字类型
procotol: 使用的特定协议

2、指定本地地址——bind()
功能&#xff1a;将套接字地址与所创建的套接字号联系起来。
格式&#xff1a;int PASCAL FAR bind(SOCKET s,const struct sockaddr FAR * name,int namelen);
参数&#xff1a;s: 是由socket()调用返回的并且未作连接的套接字描述符&#xff08;套接字号&#xff09;。
其它&#xff1a;没有错误&#xff0c;bind()返回0&#xff0c;否则SOCKET_ERROR
地址结构说明&#xff1a;
struct sockaddr_in
{
short sin_family;//AF_INET
u_short sin_port;//16位端口号&#xff0c;网络字节顺序
struct in_addr sin_addr;//32位IP地址&#xff0c;网络字节顺序
char sin_zero[8];//保留
}

3、建立套接字连接——connect()和accept()
功能&#xff1a;共同完成连接工作
格式&#xff1a;int PASCAL FAR connect(SOCKET s,const struct sockaddr FAR * name,int namelen);
SOCKET PASCAL FAR accept(SOCKET s,struct sockaddr FAR * name,int FAR * addrlen);
参数&#xff1a;同上

4、监听连接——listen()
功能&#xff1a;用于面向连接服务器&#xff0c;表明它愿意接收连接。
格式&#xff1a;int PASCAL FAR listen(SOCKET s, int backlog);

5、数据传输——send()与recv()
功能&#xff1a;数据的发送与接收
格式&#xff1a;int PASCAL FAR send(SOCKET s,const char FAR * buf,int len,int flags);
int PASCAL FAR recv(SOCKET s,const char FAR * buf,int len,int flags);
参数&#xff1a;buf:指向存有传输数据的缓冲区的指针。

6、多路复用——select()
功能&#xff1a;用来检测一个或多个套接字状态。
格式&#xff1a;int PASCAL FAR select(int nfds,fd_set FAR * readfds,fd_set FAR * writefds,
fd_set FAR * exceptfds,const struct tim FAR * timeout);
参数&#xff1a;readfds:指向要做读检测的指针
writefds:指向要做写检测的指针
exceptfds:指向要检测是否出错的指针
timeout:最大等待时间

7、关闭套接字——closesocket()
功能&#xff1a;关闭套接字s
格式&#xff1a;BOOL PASCAL FAR closesocket(SOCKET s);

 

典型过程图
2.1 面向连接的套接字的系统调用时序图
[网络编程] <wbr>socket <wbr>编程浅谈&#xff08;一&#xff09;


2.2 无连接协议的套接字调用时序图
[网络编程] <wbr>socket <wbr>编程浅谈&#xff08;一&#xff09;


2.3 面向连接的应用程序流程图
[网络编程] <wbr>socket <wbr>编程浅谈&#xff08;一&#xff09;

好了接下来我们编写一个简单的程序来看看运作过程

 

例子程序 

Visual C&#43;&#43; 2005 调试通过,请在工程的库路径里包含文件Ws2_32.lib

1&#xff0e;TCP客户端

client.cpp

-----------------------------------------------------------

#include
#include
//#include
//#include 
//#include
//#include
#include
#include
#include
char * host_name&#61;"127.0.0.1";
int port&#61;10001;
void main(int argc,char *argv[])
{
    char buf[4096];
    char message[1024];
    int socket_descriptor;
    struct sockaddr_in pin;
    struct hostent *server_host_name;
    char *message_str&#61;"hello,network\0";
    WSADATA wsaData;

    if(argc<2) {
        printf("send default srting.\n");
    } else {
        message_str&#61;argv[1];
    }


    if(WSAStartup(MAKEWORD(2,1),&wsaData)) {
        printf("Winsock initializing fail\n");
        WSACleanup();
        return ;
    }

    if((server_host_name&#61;gethostbyname(host_name))&#61;&#61;0)
    {
        perror("cant resolving localhost\n");
        WSACleanup();
        exit(1);
    }

    // bzero(&pin,sizeof(pin));
    memset(&pin, 0, sizeof(pin));
    memset(buf, 0, sizeof(buf));
    pin.sin_family&#61;AF_INET;
    pin.sin_addr.s_addr&#61;htonl(INADDR_ANY);
    pin.sin_addr.s_addr&#61;((struct in_addr *)(server_host_name->h_addr))->s_addr;
    pin.sin_port&#61;htons(port);

    if((socket_descriptor&#61;socket(AF_INET,SOCK_STREAM,0))&#61;&#61;-1) {
        perror("Error opening socket\n");
        WSACleanup();
        exit(1);
    }

    if(connect(socket_descriptor,(const sockaddr *)&pin,sizeof(pin))&#61;&#61;-1)
    {
        perror("cant connecting to server");
        closesocket(socket_descriptor);
        WSACleanup();
        exit(1);
    }

    printf("send message %s to server ...\n",message_str);
    if (send(socket_descriptor,message_str,strlen(message_str),0)&#61;&#61;-1) {
        perror("cant send message\n");
        closesocket(socket_descriptor);
        WSACleanup();
        exit(1);
    }

    printf("waiting for response from server\n");
    if (recv(socket_descriptor,buf,sizeof(buf),0)&#61;&#61;-1) {
        perror("cant receive response\n");
        closesocket(socket_descriptor);
        WSACleanup();
        exit(1);
    }

    printf("\nResponse from server:\n\n%s\n",buf);
   
    closesocket(socket_descriptor);
    WSACleanup();
   
    return ;
}

-----------------------------------------------------------

 

1&#xff0e;TCP服务端

server.cpp

-----------------------------------------------------------

#include
#include
//#include
#include
//#include
//#include
//#include
#include
#include
int port &#61; 10001;
int main ()
{
    struct sockaddr_in sin;
    struct sockaddr_in pin;
    int sock_descriptor;
    int temp_sock_descriptor;
    int size_of_addr;
    size_of_addr&#61;sizeof(pin);
    char buf[8192];
    int i, lenth;
    int ret;

    WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2,1),&wsaData)){
        printf("Winsock initializing fail\n");
        WSACleanup();
        return 0;
    }

    sock_descriptor &#61; socket(AF_INET, SOCK_STREAM, 0);
    //bzero(&sin, sizeof (sin));
    memset(&sin, 0, sizeof(sin));
    memset(buf, 0, sizeof(buf));
    sin.sin_family &#61; AF_INET;
    sin.sin_addr.s_addr &#61; htonl(INADDR_ANY);
    sin.sin_port &#61; htons (port);

    if (bind (sock_descriptor, (struct sockaddr *) &sin, sizeof (sin)) &#61;&#61; -1) {
        perror ("bind!");
        closesocket(sock_descriptor);
        WSACleanup();
        exit (1);
    }

    if (listen (sock_descriptor, 20) &#61;&#61; -1) {
        perror ("listen!");
        closesocket(sock_descriptor);
        WSACleanup();
        exit (1);
    }

    printf ("waiting for accepting connections from client\n");
    while(1) {
        temp_sock_descriptor &#61; accept(sock_descriptor,(struct sockaddr *)&pin,&size_of_addr);
        if (temp_sock_descriptor &#61;&#61; -1) {
            perror ("call to accept");
        }
       
        if (recv (temp_sock_descriptor, buf, sizeof (buf), 0) &#61;&#61; -1) {
            perror ("recv!");
            closesocket(sock_descriptor);
            WSACleanup();
            exit (1);
        }

        printf ("received:%s\n", buf);
        lenth &#61; strlen (buf);
        for (i &#61; 0; i <&#61; lenth; i&#43;&#43;) {
            buf[i] &#61; toupper (buf[i]);

        }

        if (send (temp_sock_descriptor, buf, lenth, 0) &#61;&#61; -1) {
            perror ("send!");
            closesocket(sock_descriptor);
            WSACleanup();
            exit (1);
        }

    }
   
    closesocket (temp_sock_descriptor);
    WSACleanup();
   
    return 0;
}

-----------------------------------------------------------

程序运行截图&#xff1a;




推荐阅读
  • 2016-2017学年《网络安全实战》第三次作业
    2016-2017学年《网络安全实战》第三次作业总结了教材中关于网络信息收集技术的内容。本章主要探讨了网络踩点、网络扫描和网络查点三个关键步骤。其中,网络踩点旨在通过公开渠道收集目标信息,为后续的安全测试奠定基础,而不涉及实际的入侵行为。 ... [详细]
  • 端口转发(Port Forwarding)类似于服务重定向,许多路由器中也称其为虚拟服务器(Virtual Server)。通过合理配置端口转发,可以实现外部网络对内部网络中特定设备和服务的高效访问,从而提高通信效率和灵活性。此外,正确设置端口转发还能增强网络安全,确保只有授权的流量能够进入内网,有效防止未授权访问和潜在威胁。 ... [详细]
  • 本文主要从TLS1.3的优势、部署和时间发展线介绍了这上篇文章回顾:浅谈DHCP协议 ... [详细]
  • centos 7.0 lnmp成功安装过程(很乱)
    下载nginx[rootlocalhostsrc]#wgethttp:nginx.orgdownloadnginx-1.7.9.tar.gz--2015-01-2412:55:2 ... [详细]
  • 本文介绍了如何利用HTTP隧道技术在受限网络环境中绕过IDS和防火墙等安全设备,实现RDP端口的暴力破解攻击。文章详细描述了部署过程、攻击实施及流量分析,旨在提升网络安全意识。 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 在探讨Hibernate框架的高级特性时,缓存机制和懒加载策略是提升数据操作效率的关键要素。缓存策略能够显著减少数据库访问次数,从而提高应用性能,特别是在处理频繁访问的数据时。Hibernate提供了多层次的缓存支持,包括一级缓存和二级缓存,以满足不同场景下的需求。懒加载策略则通过按需加载关联对象,进一步优化了资源利用和响应时间。本文将深入分析这些机制的实现原理及其最佳实践。 ... [详细]
  • 深入解析Wget CVE-2016-4971漏洞的利用方法与安全防范措施
    ### 摘要Wget 是一个广泛使用的命令行工具,用于从 Web 服务器下载文件。CVE-2016-4971 漏洞涉及 Wget 在处理特定 HTTP 响应头时的缺陷,可能导致远程代码执行。本文详细分析了该漏洞的成因、利用方法以及相应的安全防范措施,包括更新 Wget 版本、配置防火墙规则和使用安全的 HTTP 头。通过这些措施,可以有效防止潜在的安全威胁。 ... [详细]
  • Nginx入门指南:从零开始掌握基础配置与优化技巧
    Nginx入门指南:从零开始掌握基础配置与优化技巧 ... [详细]
  • 读书笔记来自图解HTTP1.HTTP的缺点 通信使用明文(不加密),内容可能会被窃听不验证通信方的身份,因此有可能遭遇伪装无 ... [详细]
  • 1、TCPIP 是个协议组,从下往上可分为:网络接口层、网络层、传输层和应用层。 在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP ... [详细]
  • 如何尽量处理TIMEWAIT过多?
    如何尽量处理TIMEWAIT过多?编辑内核文件etcsysctl.conf,加入以下内容:net.ipv4.tcp_syncookies1表示开启SYNCookies。当出现SYN ... [详细]
  • # 运维小白的成长日记第七天OSI七层传输层/应用层精讲!
    运维小白的成长日记第七天-OSI七层传输层应用层精讲!1、IP提供了点到点的连续接,通过IP地址可以找到目标主机。但是目标主机有很多应用,服务器到底使用哪个应用来响应客户端?通过端 ... [详细]
  • 找了很久抓包分析的一些例子,可以就是那么几个在不停的重复。抓包分析起来才觉得基本功太不够了,涉及到的东西太多,要了解的东西也太多。发这个贴的目的是有希望我们有幸一起分享您的劳动汗水和结晶建议 ... [详细]
  • 公司有个系统,比较古老,web端使用的是applet,applet作为socketclient端。另一台服务器运行socketserver.当多次执行某一个特定事务时(通过Applet,该事务会触 ... [详细]
author-avatar
日月小明空间_785
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有