[2016/8/22][Unix网络编程]第一章:①时间获取程序

一.IP和端口

IP地址是一个规定,现在使用的是IPv4,既由4个0-255之间的数字组成,在计算机内部存储时只需要4个字节即可。在计算机中,IP地址是分配给网卡的,每个网卡有一个唯一的IP地址,如果一个计算机有多个网卡,则该台计算机则拥有多个不同的IP地址,在同一个网络内部,IP地址不能相同。IP地址的概念类似于电话号码、身份证这样的概念。由于IP地址不方便记忆,所以有专门创造了域名(Domain Name)的概念,其实就是给IP取一个字符的名字,例如163.com、sina.com等。IP和域名之间存在一定的对应关系。如果把IP地址类比成身份证号的话,那么域名就是你的姓名。 

一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等,这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP 地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。        

其实在网络中只能使用IP地址进行数据传输,所以在传输以前,需要把域名转换为IP,这个由称作DNS的服务器专门来完成。 所以在网络编程中,可以使用IP或域名来标识网络上的一台设备。      为了在一台设备上可以运行多个程序,人为的设计了端口(Port)的概念,类似的例子是公司内部的分机号码。规定一个设备有216个,也就是65536个端口,每个端口对应一个唯一的程序。每个网络程序,无论是客户端还是服务器端,都对应一个或多个特定的端口号。由于0-1024之间多被操作系统占用,所以实际编程时一般采用1024以后的端口号。 下面是一些常见的服务对应的端口:

ftp:23,telnet:23,smtp:25,dns:53,http:80,https:443

使用端口号,可以找到一台设备上唯一的一个程序。  所以如果需要和某台计算机建立连接的话,只需要知道IP地址或域名即可,但是如果想和该台计算机上的某个程序交换数据的话,还必须知道该程序使用的端口号。

我们知道IP层的ip地址可以唯一标示主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。

socket

我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。

http://www.cnblogs.com/dolphinX/p/3460545.html 讲得不错,对理解下面两个程序有帮助

1.时间获取客户程序(TCP)

tips

①int main(int argc, char **argv)

argc是参数个数,二维字符串数组argv是命令行参数;

② sockaddr_in 地址结构体。元素如下:

sin_family指代协议族,在socket编程中只能是AF_INET
sin_port存储端口号(使用网络字节顺序),在linux下,端口号的范围0~65535,同时0~1024范围的端口号已经被系统使用或保留。
sin_addr存储IP地址,使用in_addr这个数据结构
sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
s_addr按照网络字节顺序存储IP地址

 ③socket函数:int socket(int domain, int type, int protocol)

 函数返回一个整型的socket描述符(sockfd:socket file descriptor文件描述符),供后面的使用,其中参数:

 1. domain:指明使用的协议族,值:
AF_INET:用于网络通信
AF_UNIX:单一Unix系统中进程间通信
2.type: 指明socket类型,值

SOCK_STREAM:流式,面向连接的比特流,顺序、可靠、双向,用于TCP通信
SOCK_DGRAM: 数据报式,无连接的,定长、不可靠  UDP通信
 3.protocol:由于指定了type,这里一般用“0”
 
一个socket的建立:int fd = socket(AF_INET, SOCK_STREAM, 0)

④inet_pton函数:int inet_pton(int af, const char *src, void *dst)

这个函数转换字符串到网络地址。

第一个参数af是地址簇;

第二个参数*src是来源地址;

第三个参数* dst接收转换后的数据。

 ⑤int connect (int sockfd, struct sockaddr * serv_addr, int addrlen);

用来将参数sockfd 的socket 连至参数serv_addr 指定的网络地址。

参数一:套接字描述符
参数二:指向数据结构sockaddr的指针,其中包括目的端口和IP地址
参数三:参数二sockaddr的长度,可以通过sizeof(struct sockaddr)获得

⑥ssize_t read(int fd,void * buf ,size_t count);
read()会把参数fd 所指的文件传送count个字节到buf指针所指的内存中。若参数count为0,则read为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。

代码:

#include	"unp.h"

int
main(int argc, char **argv)
{
	int	sockfd, n;
	char recvline[MAXLINE + 1];
	struct sockaddr_in servaddr;

	if (argc != 2)
		err_quit("usage: a.out <IPaddress>");
	/*
		    创建TCP套接字
							*/ 
	if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		err_sys("socket error");
	/*
			指定服务器的ip和端口 
									*/ 
	bzero(&servaddr, sizeof(servaddr)); //把结构体变量清零 
	servaddr.sin_family = AF_INET;//TCP协议簇 
	servaddr.sin_port   = htons(13);//htons函数,把端口号转换成二进制 

	if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) //IP地址是第一个命令行参数的值:arvg[1] 
		err_quit("inet_pton error for %s", argv[1]);
	/*
			建立和服务器的连接 
									*/ 
//调用connect发起主动打开,导致客户tcp发送一个同步分节 
	if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) //三次握手,建立连接。其中sockfd就是socket的文件描述符。 
		err_sys("connect error");
	/*
			读入并输出服务器的应答
									*/ 	
	while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
		recvline[n] = 0;	// null terminate ,结束终止符
		if (fputs(recvline, stdout) == EOF) //fputs就是I/O函数,fputs向指定文件写入字符串。参数:字符串,文件指针,遇到0终止输出。 
			err_sys("fputs error");
	}
	if (n < 0)
		err_sys("read error");

	exit(0);
}


2.时间获取服务器程序(TCP)

代码:

#include	"unp.h"
#include	<time.h>

int
main(int argc, char **argv)
{
	int					listenfd, connfd;
	struct sockaddr_in	servaddr;
	char				buff[MAXLINE];
	time_t				ticks;
//准备监听描述符的三个步骤:socket,bind,listen.通过调用这三个函数完成被动打开(准备好接受外来连接) 
	listenfd = Socket(AF_INET, SOCK_STREAM, 0);//AF_INET:采用TCP/IP协议簇;SOCK_STREAM:采用TCP协议,0是默认情况 

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family      = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY是inet_addr("0.0.0.0"),如果服务器主机有多个网络接口,服务器进程就可以在任意网络接口上受客户连接 
	servaddr.sin_port        = htons(13);//socket对应的端口(找到ip就是找到主机,再找到端口才是确定进程) 时间服务器接口都是13 

	Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); // 将socket绑定到某个IP和端口(IP标识主机,端口标识通信进程)

	Listen(listenfd, LISTENQ); // 将socket设置为监听模式,5表示等待连接队列的最大长度(排队的最大客户连接数)
								// listen函数使用主动连接套接字变为被连接套接口,使得一个进程可以接受其它进程的请求,从而成为一个服务器进程。在TCP服务器编程中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接。
								//listen函数一般在调用bind之后-调用accept之前调用。

	for ( ; ; ) {
		connfd = Accept(listenfd, (SA *) NULL, NULL);//accept:在一个套接口接受一个连接。如果accept成功返回,则服务器与客户已经正确建立连接了,此时服务器通过accept返回的套接字来完成与客户的通信。

        ticks = time(NULL);
        snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));//在字符串末尾添加 
        Write(connfd, buff, strlen(buff));// 参数1是文件描述符;参数2是指定的缓冲区,即指针,指向一段内存单元;参数3是要写入文件指定的字节数;返回值:写入文档的字节数(成功);-1(出错)
									//write函数把buff中nbyte写入文件描述符connfd所指的文档,成功时返回写的字节数,错误时返回-1.

		Close(connfd);//终止连接 
	}
}


最后结果:

client:

   #include <stdio.h>
   #include <netinet/in.h>
   #include <sys/types.h>
   #include <sys/socket.h> 
   #include <string.h>
   #include<stdlib.h>
   #include <netinet/in.h> 
   #define SA struct sockaddr
   #define MAXLINE 1000
   int main(int argc,char **argv)
   {
   //  printf("23333\n");
       int sockfd,n;
       char recvline[MAXLINE+1];
       struct sockaddr_in servaddr;
   
       if (argc!=2){
           printf("IP\n");
           exit(0);
       }
   
       if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
           printf("socket error\n");
           exit(0);
      }
   //  printf(" 333\n");
       bzero(&servaddr, sizeof(servaddr)); 
       servaddr.sin_family = AF_INET;
       servaddr.sin_port = htons(6789);
       if((inet_pton(AF_INET, argv[1], &servaddr.sin_addr)) < 0){
           printf("inet_pton error for %s\n",argv[1]);
            exit(0);
       }
       int xx = connect(sockfd, (SA *)&servaddr,sizeof(servaddr));
       if(xx < 0){
          printf("connect error\n");
          exit(0);        
        }
      	printf("已建立连接\n");
      	while((n = read(sockfd, recvline, MAXLINE)) > 0){
        	recvline[n] = '\0';
          	printf(" 33\n");
          	if(fputs(recvline, stdout) == EOF){
            	printf("fputs error\n");
               	exit(0);
           }
        }
       	if(n < 0){
            printf("read error\n");
        	exit(0);
        }
        exit(0);
   	}

server

#include <stdio.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h> 
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <unistd.h>
#define SA struct sockaddr
#define LISTENQ 10
#define MAXLINE 1000
int main(int argc, char **argv){
	int listenfd, connfd;
	struct sockaddr_in servaddr;
	char buff[MAXLINE];

	listenfd = socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(6789);

	bind(listenfd, (SA *) &servaddr,sizeof(servaddr));
	listen(listenfd, LISTENQ);
	for( ; ;){
		connfd = accept(listenfd, (SA *) NULL, NULL);
		snprintf(buff, sizeof(buff), "%s\r\n","get it!");
		write(connfd, buff, strlen(buff));
		
		close(connfd);
	}
}

tip:从vim复制代码:cat + xx.c

再复制就好啦!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值