第10章 网络编程补充案例
- 格式:doc
- 大小:207.00 KB
- 文档页数:14
C语言网络编程基础及其应用实例网络编程是计算机科学中的一个重要领域,它涉及到计算机之间的通信和数据传输。
而C语言作为一种高效且广泛使用的编程语言,也被广泛应用于网络编程领域。
本文将介绍C语言网络编程的基础知识,并通过实例来展示其应用。
一、网络编程基础在进行网络编程之前,我们首先需要了解一些基础概念。
网络编程主要涉及两个重要的概念:IP地址和端口号。
IP地址是用来唯一标识网络中的主机的地址。
它由四个十进制数组成,每个数的取值范围是0到255。
例如,192.168.0.1是一个常见的IP地址。
端口号用于标识网络中的应用程序。
一个主机可以同时运行多个应用程序,每个应用程序都会监听一个特定的端口号。
端口号的取值范围是0到65535,其中0到1023是系统保留端口号,一般用于一些常见的服务,如HTTP服务的端口号是80。
在C语言中,我们可以使用socket库进行网络编程。
socket库提供了一组函数,用于创建网络连接、发送和接收数据等操作。
下面我们通过一个简单的实例来演示如何使用C语言进行网络编程。
二、应用实例:简单的服务器和客户端我们将创建一个简单的服务器和客户端程序,通过服务器向客户端发送一条消息。
首先,我们需要创建服务器程序。
以下是服务器程序的代码:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 8080int main() {int server_fd, new_socket, valread;struct sockaddr_in address;int addrlen = sizeof(address);char *message = "Hello from server";// 创建socketif ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);// 绑定地址和端口号if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed");exit(EXIT_FAILURE);}// 监听连接请求if (listen(server_fd, 3) < 0) {perror("listen failed");exit(EXIT_FAILURE);}// 接受客户端连接if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {perror("accept failed");exit(EXIT_FAILURE);}// 发送消息给客户端send(new_socket, message, strlen(message), 0);printf("Message sent to client\n");return 0;}```接下来,我们创建客户端程序。
C#网络通讯开发实战第1 章:套接字编程编写网络运用程序是程序设计中最风趣的范畴之一。
眼看着自个编写的程序成功地经过网络完成了通讯,这是格外令人振奋的。
在这一章里,咱们将运用TCP/IP树立一个类似于Windows LiveMessenger(或ICQ)的谈天程序。
经过这个谈天程序,你将学会如安在.NET中进行网络编程,并晓得树立多用户谈天程序时会遇到的种种应战。
第2 章:串行通讯串行通讯是设备之间彼此通讯最陈旧的机制之一。
从IBM PC及其兼容机开端,简直一切的核算机都装备了一个或多个串行端口和一个并行端口。
望文生义,串行端口(serial port )每次1位地接连收发数据,而并行端口(parallel port)则运用8条独立的数据线每次收发8位数据。
虽然串行端口传输速度相对低于并行端口,但串行通讯仍然是设备衔接的盛行选项,因为它简略并且本钱较低。
虽然当今的消耗商品正在运用USB衔接替代串行衔接,可是仍有很多的设备把串行端口作为它们与外部国际衔接的仅有方法。
这一章将介绍怎么运用.NET Framework 2.0和.NET Compact Framework 2.0里新的SerialPort类完成与其他串行设备的通讯。
咱们将树立3个项目,用实例阐明怎么运用串行通讯。
第一个项目是一个谈天程序,它答应(运用串行数据线或许蓝牙相互衔接的)两台核算机进行通讯。
你能够以此程序为根底,对其进行扩大来完成与手机之类的其他外部串行设备的通讯。
你将学会怎么经过一个串行的蓝牙衔接运用A T指令经过程序来操控你的移动电话。
第二个项目是一个Pocket PC谈天程序,与前一个项目十分类似。
第三个项目展现了怎么与GPS接纳器通讯,并从中获取有用的数据用于在地图上显现当时方位。
第3 章:将指纹辨认归入.NET 程序生物特征辨认是承认个别身份最牢靠的方法之一。
如今,大概有很多人现已晓得了微软指纹阅读器(Microsoft Fingerprint Reader)。
第1章Visual C++网络编程概述Visual C++(后面简写为VC)网络编程是指用户使用MFC类库(微软基础类库)在VC编译器中编写程序,以实现网络应用。
用户通过VC编程实现的网络软件可以在网络中不同的计算机之间互传文件、图像等信息。
本章将向用户介绍基于Windows操作系统的网络编程基础知识,其开发环境是VC。
在VC编译器中,使用Windows Socket进行网络程序开发是网络编程中非常重要的一部分。
1.1 网络基础知识如果用户要进行VC网络编程,则必须首先了解计算机网络通信的基本框架和工作原理。
在两台或多台计算机之间进行网络通信时,其通信的双方还必须遵循相同的通信原则和数据格式。
本节将向用户介绍OSI七层网络模型、TCP/IP协议以及C/S编程模型。
1.1.1 OSI七层网络模型OSI网络模型是一个开放式系统互联的参考模型。
通过这个参考模型,用户可以非常直观地了解网络通信的基本过程和原理。
OSI参考模型如图1.1所示。
图1.1 OSI七层网络模型用户从OSI网络模型可以很直观地看到,网络数据从发送方到达接收方的过程中,数据的流向以及经过的通信层和相应的通信协议。
事实上在网络通信的发送端,其通信数据每到一个通信层,都会被该层协议在数据中添加一个包头数据。
而在接收方恰好相反,数据通过每一层时都会被该层协议剥去相应的包头数据。
用户也可以这样理解,即网络模型中的各层都是对等通信。
在OSI七层网络模型中,各个网络层都具有各自的功能,如表1.1所示。
表1.1 各网络层的功能协议层名功能概述物理硬件层表示计算机网络中的物理设备。
常见的有计算机网卡等数据链路层将传输数据进行压缩与加压缩网络层将传输数据进行网络传输数据传输层进行信息的网络传输会话层建立物理网络的连接表示层将传输数据以某种格式进行表示应用层应用程序接口注意:在表1.1中列出了OSI七层网络模型中各层的基本功能概述。
用户根据这些基本的功能概述会对该网络模型有一个比较全面的认识。
第十章补充案例案例10-1使用InetAddress类获取与IP信息一、案例描述1、考核知识点编号:00110004名称:InetAddress类2、练习目标➢掌握InetAddress类的相关API➢掌握如何使用InetAddress类中的方法获取计算机的主机名和IP地址等信息。
3、需求分析InetAddress类中提供了一系列与IP地址相关的方法,利用这些方法可以获取到指定计算机的主机名、IP地址以及连接状态等信息。
为了让初学者掌握InetAddress类中常用方法的使用,本案例将针对如何通过InetAddress类中的方法获取计算机的IP地址、主机名等功能进行演示。
4、设计思路(实现原理)1)编写Example01类。
2)在main()方法中,通过InetAddress类的静态方法getLocalHost()创建实例对象,并通过该对象完成获取计算机主机名和计算机IP地址的操作。
3)分别将获取到的主机名和IP地址输出。
二、案例实现import .InetAddress;import .UnknownHostException;public class Example01 {public static void main(String[] args) throws UnknownHostException {//获取本机的IP地址InetAddress address = InetAddress.getLocalHost();//以字符串形式返回IP地址String ip = address.getHostAddress();//获取此IP地址的主机名String name = address.getHostName();System.out.println("本机的ip地址是:"+ip);System.out.println("本机的hostName是:"+name);}}运行结果如图10-1所示。
《网络编程技术》实验指导书董黎刚信息与电子工程学院浙江工商大学2013-4-28 14:41:00ContentContent (1)课内实验1. Linux平台简单套接字编程 (2)课内实验2. Windows平台简单套接字编程 (4)课内实验3. html网页编程 (5)课内实验4. 客户端Web编程 (6)课内实验5. WinInet编程 (7)课内实验6. 并发套接字编程 (8)课外实验1. MFC编程 (9)课外实验2. MFC WinSock类的编程 (10)课外实验3.服务器端Web编程 (11)课外实验4. HTTP协议应用编程 (12)课外实验5. 电子邮件协议应用编程 (13)课外实验6. 网络综合程序设计 (14)附录1. 程序评分标准 (15)附录2. Linux shell commands (16)附录3. 编程类实验报告参考格式 (18)课内实验1. Linux平台简单套接字编程实验类型:设计性一、实验环境操作系统:Linux编程工具及集成开发环境:gcc, vi或anjuta二、实验目的和要求实验目的:掌握Linux平台上简单的客户机端和服务器端的套接字编程。
实验要求:(1)在Linux上,编写、编译1个客户机端程序和1个服务器端程序。
要求客户机端程序能发送请求给服务器端程序,服务器端程序收到后能发送本机时间给客户机端程序。
(2)在相同或不同机子上,先运行服务器端程序可执行文件,后运行客户机端程序可执行文件。
可选内容:(1)编写聊天程序,即客户机端程序和服务器端程序之间都能够多次发送消息给对方,也能够多次接收对方发送的消息。
(2)编写TCP和UDP两种程序。
三、实验提示(1)从/dlg/HomeTeaching_files/download/source_code/socket/v3.linux.dist.tar.Z可以下载可供参考的程序。
解压采用“zcat v3.linux.dist.tar.Z | tar xvf –”。
java网络编程案例教程Java网络编程是指使用Java语言编写程序来实现网络通信的技术。
它包括了建立网络连接、发送和接收数据等操作。
本篇文章将从简单到复杂地介绍Java网络编程的相关知识,并通过案例来帮助读者理解和掌握这一技术。
首先,我们需要了解Java网络编程的基础知识。
在Java中,网络编程主要依赖于两个核心类库:和java.io。
其中,包提供了一些类和接口来处理网络编程中的各种操作,比如Socket、ServerSocket、URL等;而java.io包则提供了一些类和接口来处理输入输出流的操作,比如InputStream、OutputStream等。
在网络编程中,我们通常需要使用Socket类来进行连接的建立。
Socket类提供了一些方法来创建客户端和服务器端的Socket对象,并进行数据传输。
下面我们通过一个简单的案例来介绍Socket的使用方法。
案例一:Socket的使用客户端代码:```import java.io.*;import .*;public class Client {public static void main(String[] args) {try {Socket socket = new Socket("127.0.0.1", 8888); OutputStream os = socket.getOutputStream(); PrintWriter pw = new PrintWriter(os);pw.write("Hello, server!");pw.flush();socket.shutdownOutput();InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));String message = null;while ((message = br.readLine()) != null) {System.out.println("Server: " + message);}br.close();is.close();pw.close();os.close();socket.close();} catch (IOException e) {e.printStackTrace();}}}```服务器端代码:```import java.io.*;import .*;public class Server {public static void main(String[] args) {try {ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server listening on port 8888..."); Socket socket = serverSocket.accept();InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));String message = null;while ((message = br.readLine()) != null) {System.out.println("Client: " + message);}OutputStream os = socket.getOutputStream();PrintWriter pw = new PrintWriter(os);pw.write("Hello, client!");pw.flush();pw.close();os.close();br.close();is.close();socket.close();serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}```在这个案例中,我们首先在服务器端创建了一个ServerSocket对象,并通过accept()方法等待客户端的连接。
第10章C#的高级应用本章介绍C#程序的高级应用,包括多线程编程、数据库编程、及Web编程、XML 及Web Service编程、网络通讯编程、C#程序与其他程序的互操作等。
10.1 多线程编程以前所介绍的程序多数是单线程的,即一个程序只有一条从头至尾的执行路线。
然而现实世界中的很多过程都具有多种途径同时运作,例如服务器可能需要同时处理多个客户机的请求。
在Windows操作系统中,不仅多个应用程序能同时运行,而且在同一程序内部也可以有多个线程同时运行,这就是多线程。
C#语言可以方便地开发出具有多线程功能的应用程序。
10.1.1 多线程的相关概念1.程序、进程与线程程序是一段静态的代码,它是应用软件执行的蓝本。
进程是应用程序的一次动态执行过程,它对应了从代码加载、执行到执行完毕的一个完整过程,这个过程也是进程本身从产生、发展到消亡的过程。
作为执行蓝本的同一段程序,可以被多次加载到系统的不同内存区域分别执行,形成不同的进程。
线程是比进程更小的执行单位。
一个进程在其执行过程中,可以产生多个线程,形成多条执行线索。
每条线索有它自身的产生、存在和消亡的过程,也是一个动态的概念。
每个进程都有一段专用的内存区域,而线程间可以共享相同的内存单元(包括代码与数据),并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。
2.多线程处理的优点多线程处理可以同时运行多个任务。
例如,文字处理器应用程序在处理文档的同时,可以检查拼写(作为单独的任务),或者完成打印的任务。
由于多线程应用程序将程序划分成独立的任务,因此可以在以下方面显著提高性能:(1)多线程技术使程序的响应速度更快,因为用户界面可以在进行其他工作的同时一直处于活动状态。
(2)当前没有进行处理的任务可以将处理器时间让给其他任务。
(3)占用大量处理时间的任务可以定期将处理器时间让给其他任务。
(4)可以随时停止任务。
(5)可以分别设置各个任务的优先级以优化性能。
C++⼀个⽹络编程实例学习C++已经有⼀段时间了,⼀直都是学习基础的东西,每次写的代码都⽐较少,没有明确的学习⽬标,基础还是基础,漫⽆边际的,基本上都是做⼀道或者⼏道算法题,连⼀个⼩⼩的实战都没有,也不知道⾃⼰学得怎么样了,现在终于有⼀个⼩⼩的实战了《C++ ⼀个⽹络编程实例》。
由于⾃⼰⼀直在做C#,只能业余时间学习C++,都说C++ 是那么的难,暂时还没有感觉到有多难,毕竟写代码也有两年多了。
我要学习多久才能进⼀家做C++研发的公司呢?相信在不远处有⼀家C++研发公司在等着我。
这只是⼀个⼩⼩的实例,包括Socket编程、多线程、⽂件操作。
简单介绍:他实现了点对点聊天,⼀个服务器,⼀个客户端,主线程⽤来发送数据,启动⼀个⼦线程⽤来接收数据,服务器记录聊天内容。
他只是⽤上了上⾯所说的三个技术,如果你对上⾯三个技术不是很熟,或许对你有点帮助,如果你很熟,既然来了希望你能指导⼀下我,如果你是⾼⼿希望你能指导⼀下我的编码问题。
我太渴望写出⾼效简洁的代码。
废话就少说了,程序⾥处处都是注释,你可以选择看看我的代码,或是选择直接运⾏看看,《》。
服务器代码:// Server.cpp : 定义控制台应⽤程序的⼊⼝点。
#include "stdafx.h"#include <windows.h>#include <process.h>#include <iostream>#include "FileLog.h"#include "time.h"using namespace std;#pragma comment(lib,"ws2_32.lib")//多线程调⽤的⽅法只有⼀个指针型的参数,有时候需要多个参数,所以定义⼀个结构,参数作为结构的字段typedef struct _receiveStruct{SOCKET *Socket;FileLog *fileLog;_receiveStruct(SOCKET *_socket,FileLog *_fileLog):Socket(_socket),fileLog(_fileLog){}} ReceiveStruct;//获取今天⽇期的字符串string GetDate(const char *format){time_t tm;struct tm *now;char timebuf[20];time(&tm);now=localtime(&tm);strftime(timebuf,sizeof(timebuf)/sizeof(char),format,now);return string(timebuf);}//接收数据线程void receive(PVOID param){ReceiveStruct* receiveStruct=(ReceiveStruct*)param;char buf[2048];int bytes;while(1){//接收数据if((bytes=recv(*receiveStruct->Socket,buf,sizeof(buf),0))==SOCKET_ERROR){cout<<"接收数据失败!\n";_endthread();//终⽌当前线程}buf[bytes]='\0';cout<<"客户端说:"<<buf<<endl;receiveStruct->fileLog->Write("客户端 ").WriteLine(GetDate("%Y-%m-%d %H:%M:%S").c_str()).WriteLine(buf);//记录聊天内容}}//获取本机IPin_addr getHostName(void){char host_name[255];if (gethostname(host_name, sizeof(host_name)) == SOCKET_ERROR) {cout<<"Error %d when getting local host name."<<WSAGetLastError();Sleep(3000);exit(-1);}//从主机名数据库中得到对应的“IP”struct hostent *phe = gethostbyname(host_name);if (phe == 0) {cout<<"Yow! Bad host lookup.";Sleep(3000);exit(-1);}struct in_addr addr;memcpy(&addr, phe->h_addr_list[0], sizeof(struct in_addr));return addr;}//启动服务器SOCKET StartServer(void){//创建套接字SOCKET serverSocket;if((serverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){cout<<"创建套接字失败!";Sleep(3000);exit(-1);}short port=1986;struct sockaddr_in serverAddress;//初始化指定的内存区域memset(&serverAddress,0,sizeof(sockaddr_in));serverAddress.sin_family=AF_INET;serverAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);serverAddress.sin_port = htons(port);//绑定if(bind(serverSocket,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){cout<<"套接字绑定到端⼝失败!端⼝:"<<port;Sleep(3000);exit(-1);}//进⼊侦听状态if(listen(serverSocket,SOMAXCONN)==SOCKET_ERROR){cout<<"侦听失败!";Sleep(3000);exit(-1);}//获取服务器IPstruct in_addr addr = getHostName();cout<<"Server "<<inet_ntoa(addr)<<" : "<<port<<" is listening......"<<endl;return serverSocket;}//接收客户端连接SOCKET ReceiveConnect(SOCKET &serverSocket){SOCKET clientSocket;//⽤来和客户端通信的套接字struct sockaddr_in clientAddress;//⽤来和客户端通信的套接字地址memset(&clientAddress,0,sizeof(clientAddress));//初始化存放客户端信息的内存int addrlen = sizeof(clientAddress);//接受连接if((clientSocket=accept(serverSocket,(sockaddr*)&clientAddress,&addrlen))==INVALID_SOCKET){ cout<<"接受客户端连接失败!";Sleep(3000);exit(-1);}cout<<"Accept connection from "<<inet_ntoa(clientAddress.sin_addr)<<endl;return clientSocket;}//发送数据void SendMsg(SOCKET &clientSocket,FileLog &fileLog){char buf[2048];if(send(clientSocket,buf,strlen(buf),0)==SOCKET_ERROR){cout<<"发送数据失败!"<<endl;Sleep(3000);exit(-1);}fileLog.Write("服务器 ").WriteLine(GetDate("%Y-%m-%d %H:%M:%S").c_str()).WriteLine(buf);//记录聊天内容 }}int main(int argc, char* argv[]){WSADATA wsa;//WSADATA结构被⽤来保存函数WSAStartup返回的Windows Sockets初始化信息//MAKEWORD(a,b)是将两个byte型合并成⼀个word型,⼀个在⾼8位(b),⼀个在低8位(a)if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){cout<<"套接字初始化失败!";Sleep(3000);exit(-1);}SOCKET serverSocket=StartServer();//启动服务器SOCKET clientSocket=ReceiveConnect(serverSocket);//接收客服端的链接FileLog fileLog;fileLog.Open(GetDate("%Y%m%d").append(".log").c_str());//打开记录聊天内容⽂件ReceiveStruct receiveStruct(&clientSocket,&fileLog);_beginthread(receive,0,&receiveStruct);//启动⼀个接收数据的线程SendMsg(clientSocket,fileLog);//发送数据fileLog.Close();//关闭⽂件closesocket(clientSocket);//关闭客户端套接字(马上发送FIN信号,所有没有接收到或是发送完成的数据都会丢失) closesocket(serverSocket);//关闭服务器套接字//清理套接字占⽤的资源WSACleanup();return 0;} 客户端代码:// Client.cpp#include "stdafx.h"#include <windows.h>#include <process.h>#include <iostream>using namespace std;#pragma comment(lib,"ws2_32.lib")//接收数据void Receive(PVOID param){char buf[2096];while(1){SOCKET* sock=(SOCKET*)param;int bytes;if((bytes=recv(*sock,buf,sizeof(buf),0))==SOCKET_ERROR){printf("接收数据失败!\n");exit(-1);}buf[bytes]='\0';cout<<"服务器说:"<<buf<<endl;}}//获取服务器IPunsigned long GetServerIP(void){//把字符串的IP地址转化为u_longchar ipStr[20];//⽤第⼆个参数填充第⼀个参数所指的内存,填充的长度为第三个参数的⼤⼩memset(ipStr,0,sizeof(ipStr));cout<<"请输⼊你要链接的服务器IP:";cin>>ipStr;unsigned long ip;if((ip=inet_addr(ipStr))==INADDR_NONE){cout<<"不合法的IP地址:";}return ip;}//链接服务器void Connect(SOCKET &sock){unsigned long ip=GetServerIP();//把端⼝号转化成整数short port=1986;cout<<"Connecting to "<<inet_ntoa(*(in_addr*)&ip)<<" : "<<port<<endl;struct sockaddr_in serverAddress;memset(&serverAddress,0,sizeof(sockaddr_in));serverAddress.sin_family=AF_INET;serverAddress.sin_addr.S_un.S_addr= ip;serverAddress.sin_port = htons(port);//建⽴和服务器的连接if(connect(sock,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){ cout<<"建⽴连接失败:"<<WSAGetLastError();Sleep(3000);exit(-1);}}//发送数据void SendMsg(SOCKET &sock){char buf[2048];while(1){//从控制台读取⼀⾏数据gets_s(buf);cout<<"我说:";//发送给服务器if(send(sock,buf,strlen(buf),0)==SOCKET_ERROR){cout<<"发送数据失败!";exit(-1);}}}int main(int argc, char* argv[]){WSADATA wsa;//初始化套接字DLLif(WSAStartup(MAKEWORD(2,2),&wsa)!=0){cout<<"套接字初始化失败!";Sleep(3000);exit(-1);}//创建套接字SOCKET sock;if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){cout<<"创建套接字失败!";exit(-1);}Connect(sock);//链接服务器_beginthread(Receive,0,&sock);//启动接收数据线程SendMsg(sock);//发送数据//清理套接字占⽤的资源WSACleanup();return 0;} ⽂件操作代码(FileLog.h):#include "iostream"#include "string.h"#include <windows.h>using namespace std;class FileLog{private:CRITICAL_SECTION cs;HANDLE fileHandle;{EnterCriticalSection(&cs);// 进⼊临界区}void UnLock(){LeaveCriticalSection(&cs);//离开临界区}public:FileLog(){InitializeCriticalSection(&cs);//初始化临界区fileHandle=INVALID_HANDLE_VALUE;//先初始化为错误的句柄}~FileLog(){if(fileHandle!=INVALID_HANDLE_VALUE){//CloseHandle的功能是关闭⼀个打开的对象句柄,该对象句柄可以是线程句柄,也可以是进程、信号量等其他内核对象的句柄 CloseHandle(fileHandle);}DeleteCriticalSection(&cs);//删除临界区}BOOL Open(const char *fileName);//打开⽂件FileLog& Write(const char *content);//向⽂件中写⼊内容FileLog& WriteLine(const char *content);//向⽂件中写⼊内容BOOL Read(char *buf,int size);//读⽂件内容BOOL Close();//关闭⽂件}; ⽂件操作代码(FileLog.app):#include "stdafx.h"#include "FileLog.h"//打开⽂件BOOL FileLog::Open(const char *fileName){if(fileHandle==INVALID_HANDLE_VALUE){fileHandle=CreateFile(fileName,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);if(fileHandle!=INVALID_HANDLE_VALUE){SetFilePointer(fileHandle,0,NULL,FILE_END);return TRUE;}}return FALSE;}//写⽂件返回当前对象的引⽤,实现连接操作FileLog& FileLog::Write(const char *content){Lock();if(fileHandle!=INVALID_HANDLE_VALUE){DWORD dwSize=0;WriteFile(fileHandle,content,strlen(content),&dwSize,NULL);//写}//开始的时候少写了这句,由于加的锁没有释放,⼀个线程占⽤之后,导致其他线程只能⼀直等待,好久都没有找到原因。
网络基础协议的概念什么是协议从应用的角度出发,协议可理解为“规则”,是数据传输和数据的解释的规则。
假设,A、B双方欲传输文件。
规定:第一次,传输文件名,接收方接收到文件名,应答OK给传输方;第二次,发送文件的尺寸,接收方接收到该数据再次应答一个OK;第三次,传输文件内容。
同样,接收方接收数据完成后应答OK表示文件内容接收成功。
由此,无论A、B之间传递何种文件,都是通过三次数据传输来完成。
A、B之间形成了一个最简单的数据传输规则。
双方都按此规则发送、接收数据。
A、B之间达成的这个相互遵守的规则即为协议。
这种仅在A、B之间被遵守的协议称之为原始协议。
当此协议被更多的人采用,不断的增加、改进、维护、完善。
最终形成一个稳定的、完整的文件传输协议,被广泛应用于各种文件传输过程中。
该协议就成为一个标准协议。
最早的ftp协议就是由此衍生而来。
TCP协议注重数据的传输。
http协议着重于数据的解释。
典型协议传输层常见协议有TCP/UDP协议。
应用层常见的协议有HTTP协议,FTP协议。
网络层常见协议有IP协议、ICMP协议、IGMP协议。
网络接口层常见协议有ARP协议、RARP协议。
TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的通信协议。
UDP用户数据报协议(User Datagram Protocol)是参考模型中一种无连接的协议,提供面向事务的简单不可靠信息传送服务。
HTTP(Hyper Text Transfer Protocol)是上应用最为广泛的一种。
FTP文件传输协议(File Transfer Protocol)IP协议是互联协议(Internet Protocol)ICMP协议是Internet控制协议(Internet Control Message Protocol)它是的一个子协议,用于在IP、器之间传递控制消息。
IGMP协议是Internet 组管理协议(Internet Group Management Protocol),是因特网协议家族中的一个组播协议。
第十章补充案例案例10-1使用InetAddress类获取与IP信息一、案例描述1、考核知识点编号:4名称:InetAddress类2、练习目标➢掌握InetAddress类的相关API➢掌握如何使用InetAddress类中的方法获取计算机的主机名和IP地址等信息。
3、需求分析InetAddress类中提供了一系列与IP地址相关的方法,利用这些方法可以获取到指定计算机的主机名、IP地址以及连接状态等信息。
为了让初学者掌握InetAddress类中常用方法的使用,本案例将针对如何通过InetAddress类中的方法获取计算机的IP地址、主机名等功能进行演示。
4、设计思路(实现原理)1)编写Example01类。
2)在main()方法中,通过InetAddress类的静态方法getLocalHost()创建实例对象,并通过该对象完成获取计算机主机名和计算机IP地址的操作。
3)分别将获取到的主机名和IP地址输出。
二、案例实现import .InetAddress;import .UnknownHostException;public class Example01 {public static void main(String[] args) throws UnknownHostException {//获取本机的IP地址InetAddress address = InetAddress.getLocalHost();//以字符串形式返回IP地址String ip = address.getHostAddress();//获取此IP地址的主机名String name = address.getHostName();System.out.println("本机的ip地址是:"+ip);System.out.println("本机的hostName是:"+name);}}运行结果如图10-1所示。
图10-1运行结果三、案例总结1、InetAddress类用于封装一个IP地址,并提供了一系列与IP地址相关的方法,其中,getByName(String host)方法表示获取指定主机的IP地址,常用于获取远程计算机的IP信息,isReachable(int timeout)方法表示判断指定的时间内IP地址是否可以到达,常用于测试网络是否通畅。
2、InetAddress类的getHostName()方法是用来获取IP地址的主机名,而为什么有的时候获取到的不是主机名而是域名?案例10-2UDP网络程序一、案例描述1、考核知识点编号:名称:DatagramPacket类和DatagramSocket类2、练习目标➢掌握DatagramPacket类和DatagramSocket类的作用➢掌握如何使用DatagramPacket类和DatagramSocket类通过编写简单的UDP程序。
3、需求分析DatagramPacket用于封装UDP通信中发送或者接收的数据,DatagramSocket类用于发送和接收DatagramPacket数据包。
为了让初学者掌握这两个类的作用,本案例将通过DatagramPacket 类和DatagramSocket类实现简单的数据通信,并通过观察两个命令行窗口中数据输出的先后顺序,从而掌握UDP网络程序中接收端和发送端的执行原理。
4、设计思路(实现原理)1)编写数据接收类ReceiveDemo,在ReceiveDemo类中创建接收端的Socket服务对象,并依次编写创建数据包、调用接收方法、解析数据包并向命令行输出内容,释放资源等操作。
2)编写数据发送类SendDemo,在SendDemo类中创建发送端的Socket服务对象,并依次编写创建数据包,打包数据、发送数据、释放资源等操作。
3)依次执行ReceiveDemo和SendDemo类,观察命令行输出变化。
二、案例实现UDP网络程序中接受数据端,代码如下:import java.io.IOException;import .DatagramPacket;import .DatagramSocket;import .InetAddress;public class ReceiveDemo {public static void main(String[] args) throws IOException {// 创建接收端Socket服务对象DatagramSocket ds = new DatagramSocket(12306);// 创建数据包(接收容器)byte[] bys = new byte[1024];DatagramPacket dp = new DatagramPacket(bys, bys.length);System.out.println("接受数据服务已打开,等待接受数据");// 调用接收方法ds.receive(dp);// 解析数据包,把数据显示在控制台InetAddress address = dp.getAddress();String ip = address.getHostAddress();byte[] bys2 = dp.getData();int length = dp.getLength();String s = new String(bys2, 0, length);System.out.println(ip + "***" + s);System.out.println("接受数据完毕,接受数据服务关闭");// 释放资源ds.close();}}UDP网络程序中发送数据端,代码如下:import java.io.IOException;import .DatagramPacket;import .DatagramSocket;import .InetAddress;public class SendDemo {public static void main(String[] args) throws IOException {// 创建发送端Socket服务对象DatagramSocket ds = new DatagramSocket();// 创建数据,并把数据打包String str = "hello,udp,我来了";byte[] bys = str.getBytes();int length = bys.length;InetAddress address = InetAddress.getByName("127.0.0.1");int port = 12306;DatagramPacket dp = new DatagramPacket(bys, length, address, port);System.out.println("发送数据服务已打开");System.out.println("发送数据是:"+str);// 发送数据ds.send(dp);System.out.println("发送完毕,关闭服务");// 释放资源ds.close();}}运行接受端程序,运行结果如图10-2所示。
图10-2运行结果运行发送端程序,运行结果如图10-3所示。
图10-3运行结果观察接受端控制台的输出,运行结果如图10-4所示。
图10-4运行结果从图10-2中可以看出,当运行ReceiveDemo类时,程序会在receive()方法处停顿,并一直处于停滞状态。
当运行SendDemo类时,ReceiveDemo类中的receive()方法接受到了数据,并向下执行直到程序结束。
三、案例总结1、在创建发送端的DatagramSocket对象时,可以不指定端口号,而案例中指定端口号目的就是,为了每次运行时接收端的getPort()方法返回值都是一致的,否则发送端的端口号由系统自动分配,接收端的getPort()方法的返回值每次都不同。
2、运行例程ReceiveDemo,有时会出现如图10-5所示的异常。
图10-5运行结果出现图中所示的情况,是因为在一台计算机中,一个端口号上只能运行一个程序,而我们编写的UDP 程序所使用的端口号已经被其它的程序占用。
遇到这种情况,可以在命令行窗口输入"netstat -anb"命令来查看当前计算机端口占用情况,具体如图10-6所示。
图10-6端口占用情况案例10-3多线程的UDP网络程序一、案例描述1、考核知识点编号:00110007名称:UDP案例2、练习目标➢通过编写多线程的UDP网络程序,掌握如何在单个窗口中实现接收与发送数据。
3、需求分析在上一个案例中,通过两个命令行窗口输出数据让我们初步了解了单线程的UDP网络程序,为了让初学者更加直观和深入的掌握网络编程,本案例将整合多线程技术,在同一个命令行窗口中同时实现接收和发送数据的功能。
4、设计思路(实现原理)1)编写数据接收类ReceiveThread,该类实现了Runnable接口,重写run()方法实现不断接受客户端发送数据的功能。
2)编写数据发送类SendThread,该类同样实现了SendThread接口,重写run()方法实现通过键盘录入数据,将数据向接收端发送的功能。
3)编写测试类Example02,在main()方法中,同时启动接收端和发送端程序。
二、案例实现UDP网络程序中接受数据端,代码如下:import java.io.IOException;import .DatagramPacket;import .DatagramSocket;public class ReceiveThread implements Runnable {public void run() {try {// 创建接收端Socket对象DatagramSocket ds = new DatagramSocket(10086);// 创建数据包while (true) {byte[] bys = new byte[1024];DatagramPacket dp = new DatagramPacket(bys, bys.length);//接收数据ds.receive(dp);// 解析数据String ip = dp.getAddress().getHostAddress();String s = new String(dp.getData(), 0, dp.getLength());System.out.println("接收端:从" + ip + " 主机接收到的数据是: " + s);if ("bye".equals(s)) {System.out.println("******聊天室关闭******");ds.close();break;}}} catch (IOException e) {e.printStackTrace();}}}UDP网络程序中发送数据端,代码如下:import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import .DatagramPacket;import .DatagramSocket;import .InetAddress;public class SendThread implements Runnable {public void run() {try {// 创建发送端Socket对象DatagramSocket ds = new DatagramSocket();// 封装键盘录入BufferedReader br = new BufferedReader(new InputStreamReader(System.in));// 创建数据,并打包String line = null;while ((line = br.readLine()) != null) {byte[] bys = line.getBytes();DatagramPacket dp = new DatagramPacket(bys, bys.length,InetAddress.getByName("172.16.26.21"), 10086);ds.send(dp);if ("bye".equals(line)) {// 释放资源br.close();ds.close();break;}}// 释放资源br.close();ds.close();} catch (IOException e) {e.printStackTrace();}}}编写测试类Example02,代码如下:public class Example02 {public static void main(String[] args) {SendThread st = new SendThread();ReceiveThread rt = new ReceiveThread();Thread t1 = new Thread(st);Thread t2 = new Thread(rt);t1.start();t2.start();}}运行Example02,依次键入“hello itcast”和“bye”后,结果如图10-7所示。