网络常识

OSI 7层模型(人机交互)

物理层、数据链路层、网络层、传输层、会话层、表现层、应用层

常见协议:

tcp/udp/ip/ftp/http...

IP地址--就是计算机在网络中的地址,是一个32位的整数(IPV4),目前也有IPV6

IP地址在计算机中,以一个整数格式保存。因此IP地址在底层的描写方式:8位16进制。点分10进制是人类描述IP地址的主要方式。每个字节计算一个10进制的整数,中间用 “.”隔开。

192.168.0.20(点分十进制0-255)

==0xC0 A8 00 14(8位16进制)

IP地址分为A B C D 4类。

子网掩码--判断计算机是不是在一个局域网上

166.111.160.1与166.111.161.45

子网掩码:255.255.254.0

166.111.160.1

255.255.254.0  (位与)

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

166.111.160.0

166.111.161.45

255.255.254.0  (位与)

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

166.111.160.0

结论:166.111.160.1与166.111.161.45在同一个局域网

IP地址只能定位计算机,但没有访问权限。

端口会开放访问的权限。端口可以用来定位计算机中的某个进程。

网络编程必须提供IP地址和端口号。

端口号是unsigned short,范围:0-65535

0-1023 固有端口(不推荐使用)计算机预留

1024-48XX 程序员使用的端口  安装某些程序也会占用,但很少

48XX - 65535 不建议用,不稳定

MAC地址,物理地址,是网卡的物理地址。IP地址和MAC地址绑定在一起。

字节次序--计算机在存储整数时,有从高到低 和 从低到高之分,叫字节次序。字节次序在计算机中不确定,在网络传输的过程中是固定的。

因此,对于端口,需要本地格式和网络格式之间的转换。

域名:俗称网址,就是IP地址的助记,通过域名解析服务器 网址解析成IP地址完成访问。

网络编程--Windows/Unix 都支持

socket编程

socket--插座、套接字(IP + 端口)

关于socket编程的一些函数和常识

socket编程分为:一对一  和 一对多

一对一:

socket通信包括本地通信(ipc)和网络通信

一对一通信模型:

服务器端编程步骤:

1 创建一个socket,使用socket()

int socket(int domain,int type,int protocol)

domain--域,用来选择协议

PF_UNIX  PF_LOCAL  PF_FILE 本地通信

PF_INET  网络通信

PF_INET6 网络通信(IPV6)

注:PF也可以换成AF

type--用来选择通信类型

SOCK_STREAM --数据流,针对TCP协议

SOCK_DGRAM --数据报,针对UDP协议

protocol--本来应该用来指定协议,但没用了,因为协议已经被前2个参数指定,给 0即可

返回socket描述符,失败返回-1

2 准备通信地址

关于通信地址有3个结构体:

struct sockaddr{

int sa_family;//协议

char sa_data[];//地址

}

这个结构sockaddr不被真正使用,只是用来做相关函数的参数(不存数据)。

本地通信使用结构体:

#include<sys/un.h>

struct sockaddr_un{

int sun_family;//协议

char sun_path[];//socket文件的路径

}

网络通信使用结构体:

#include<netinet/in.h>

struct sockaddr_in{

int sin_family;//协议

short port;//端口号

struct in_addr sin_addr;//IP地址

}

3 绑定函数bind()

bind(int sockfd,sockaddr,length)

4 通信(read/write)

5 关闭 close(sockfd)

客户端编程步骤:

与服务器端基本一样,除了第三步,第三步使用connect(),参数与bind一样

注:服务器和客户端数据交互时,读写必须必须保持一致性(一边读,另一方写)

查看本机IP地址的命令:

Windows --ipconfig

Unix -- ifconfig

whereis 可以查看命令所在的目录

ping IP地址 可以检测网络是否畅通

本地通信实例:

服务器端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<string.h>

4 #include<unistd.h>

5 #include<sys/socket.h>

6 #include<sys/un.h>

7

8 int main(){

9  int sockfd = socket(PF_UNIX,SOCK_DGRAM,0);

10  if(sockfd == -1) perror("socket"),exit(-1);

11  struct sockaddr_un addr;

12  addr.sun_family = PF_UNIX;//与socket第一个参数保持一致

13  strcpy(addr.sun_path,"a.sock");

14  int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));

15  if(res == -1) perror("bind"),exit(-1);

16  printf("bind ok!\n");

17  char buf[100]={};

18  res = read(sockfd,buf,sizeof(buf));

19  printf("读了%d字节k,内容%s\n",res,buf);

20  close(sockfd);

21  return 0;

22 }

客户端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<string.h>

4 #include<unistd.h>

5 #include<sys/socket.h>

6 #include<sys/un.h>

7

8 int main(){

9   int sockfd = socket(PF_UNIX,SOCK_DGRAM,0);

10   if(sockfd == -1) perror("socket"),exit(-1);

11   struct sockaddr_un addr;

12   addr.sun_family = PF_UNIX;

13   strcpy(addr.sun_path,"a.sock");

14   int res = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));

15   if(res == -1) perror("connect"),exit(-1);

16   printf("connect ok!\n");

17   write(sockfd,"hello",5);

18   close(sockfd);

19   return 0;

20  }

网络通信:

服务器端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<string.h>

4 #include<unistd.h>

5 #include<sys/socket.h>

6 #include<netinet/in.h>

7

8 int main(){

9  int sockfd = socket(PF_INET,SOCK_DGRAM,0);

10  if(sockfd == -1) perror("socket"),exit(-1);

11  struct sockaddr_in addr;

12  addr.sin_family = PF_INET;

13  addr.sin_port =htons(2222);//端口

14  addr.sin_addr.s_addr =inet_addr("192.168.13.73");//服务器ip地址

//inet_addr将点分十进制转换成整数ip

15  int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));

16  if(res == -1) perror("bind"),exit(-1);

17  char buf[100]={};

18  res =read(sockfd,buf,100);

19  printf("读到了res=%d字节,内容是%s\n",res,buf);

20  return 0;

21 }

客户端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<string.h>

4 #include<unistd.h>

5 #include<sys/socket.h>

6 #include<netinet/in.h>

7

8 int main(){

9  int sockfd = socket(PF_INET,SOCK_DGRAM,0);

10  if(sockfd == -1) perror("socket"),exit(-1);

11  struct sockaddr_in addr;

12  addr.sin_family = PF_INET;

13  addr.sin_port =htons(2222);

14  addr.sin_addr.s_addr =inet_addr("192.168.13.73");/服务器ip地址

//inet_addr将点分十进制转换成整数ip

//服务器端和客户端的ip都是服务器ip地址

15  int res = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));

16  if(res == -1) perror("bind"),exit(-1);

17  write(sockfd,"hello",5);

18  return 0;

19 }

TCP 一对多编程步骤:

服务器端:

1 调用socke()创建socket,type必须是SOCK_STREAM(保证使用TCP模式)

2 准备通信地址sockaddr_in

3 bind()绑定

4 监听 listen(),为accept()做准备

5 等待客户端的连接accept()

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)

参数sockfd就是第一步的socket

参数addr就是链接上来的客户端的通信地址

参数len是一个传入传出参数,传入通信地址的大小,传出客户端通信地址  的大小

(要准备一个sockaddr_in 结构来存放客户端通信地址)

返回新的socket描述符,用来和客户端进行通信

6 读写数据 read/write

7 关闭socket

注:第一步的socket主要用于等待连接,不参与信息交互。第五步的socket主要用于和客户端之间的通信

客户端:

1 调用socke()创建socket,type必须是SOCK_STREAM(保证使用TCP模式)

2 准备通信地址sockaddr_in

3 connect()绑定

4 通信(read/write)

5 关闭 close(sockfd)

TCP---一对多实例:

服务器端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<string.h>

4 #include<sys/socket.h>

5 #include<netinet/in.h>

6 #include<arpa/inet.h>

7 #include<signal.h>

8 int sockfd;

9 void fa(){

10   close(sockfd);

11   printf("服务器关闭\n");

12   exit(0);

13 }

14 int main(){

15   signal(SIGINT,fa);//ctrl+c 信号关闭服务器

16   sockfd = socket(PF_INET,SOCK_STREAM,0);//创建

17   if(sockfd == -1) perror("socket"),exit(-1);

18   struct sockaddr_in addr;

19   addr.sin_family = PF_INET;

20   addr.sin_port = htons(2222);//端口

21   addr.sin_addr.s_addr = inet_addr("192.168.13.85");//服务器ip

22   //解决重启时地址被占用问题

23   int reuseaddr = 1;

24  setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,

&reuseaddr,sizeof(reuseaddr) );

25   int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));

//绑定,激活端口

26   if(res == -1) perror("bind"),exit(-1);

27   printf("bind ok\n");

28   listen(sockfd,100);//监听

29   while(1){

30    struct sockaddr_in from;//存放连接的客户端信息

31    socklen_t len = sizeof(from);

32    int fd = accept(sockfd,(struct sockaddr*)&from,&len);

//等待客户端连接

33    char* fromip = inet_ntoa(from.sin_addr);

34    printf("客户端%s连接成功\n",fromip);

35    pid_t pid = fork();//创建子进程(目前还为学习线程)

36    if(pid == 0){

37      while(1){

38        char buf[100] = {};

39        read(fd,buf,100);

40        printf("buf=%s\n",buf);

41        if(strcmp(buf,"byp")==0) break;

42        write(fd,buf,strlen(buf));

43      }

44     close(fd);

45     exit(0);

46    }

47    close(fd);

48   }

客户端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<string.h>

4 #include<sys/socket.h>

5 #include<netinet/in.h>

6 #include<arpa/inet.h>

7

8 int main(){

9   int sockfd = socket(PF_INET,SOCK_STREAM,0);

10   if(sockfd == -1) perror("socket"),exit(-1);

11   struct sockaddr_in addr;

12   addr.sin_family = PF_INET;

13   addr.sin_port = htons(2222);//端口

14   addr.sin_addr.s_addr = inet_addr("192.168.13.85");//服务器ip

15   int res = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));//连接

16   if(res == -1) perror("bind"),exit(-1);

17   printf("connect ok\n");

18   while(1){

19     char word[100] ={};

20     printf("请输入要说的话\n");

21     scanf("%s",word);

22     write(sockfd,word,strlen(word));

23     if(strcmp(word,"bye")==0) break;

24     char buf[100] = {};

25     read(sockfd,buf,100);

26     printf("buf=%s\n",buf);

27   }

28   close(sockfd);

29   return 0;

30 }

基于TCP协议的服务器和客户端直接的通信除了用read()/write()还可以用

recv()/send()

UDP --用户数据报协议

关于TCP和UDP的区别:

TCP -- 有连接协议,在通信的全程保持连接

TCP优点:重发一切错误数据,保证数据的正确和完整,缺点:服务器端压力

非常大,资源占用率比较高。

UDP -- 无连接协议,在发送数据的时候连接一下,不保持任何的连接

UDP优点:效率高,资源占用少。缺点:不保证数据的完整和正确。

UDP网络编程的函数 --发送数据和接受数据

sendto() 和 recvfrom()

几点注意:

1 第二步准备通信地址,都是服务器端的通信地址

2 客户端的通信地址,TCP用accept()函数拿,UDP用recvfrom拿(发送端口)。

客户端的端口是自动分配的。

3 TCP的信息交互函数:read/write/send/recv

UDP的信息交互函数:read/write/send/recv,但上面的函数不能取得发送方通信地址,因此更多时候,使用sendto/recvfrom

4 网络信息接收函数 一般会阻塞代码

5 服务器端都必须使用bind(),bind()函数的作用就是服务器端开发一个端口(把端口和进程绑定起来)。而客户端自动完成的。

UDP实例:

服务器端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<sys/socket.h>

4 #include<netinet/in.h>

5 #include<arpa/inet.h>

6 #include<string.h>

7

8 int main(){

9 int sockfd =socket(PF_INET,SOCK_DGRAM,0);//创建

10 if(sockfd == -1) perror("socket"),exit(-1);

11 struct sockaddr_in addr;

12 addr.sin_family = PF_INET;

13 addr.sin_port = htons(2222);//端口

14 addr.sin_addr.s_addr = INADDR_ANY;//本机IP

15 int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));//开放端口

16 if(res == -1) perror("bind"),exit(-1);

17 printf("bind ok\n");

18 char buf[100] ={};

19 struct sockaddr_in from;//用于保存客户端信息,以便回发信息

20 socklen_t len = sizeof(from);

21 recvfrom(sockfd,buf,100,0,(struct sockaddr*)&from,&len);//接收信息

22 //read(sockfd,buf,100);

23 printf("buf=%s\n",buf);

24 sendto(sockfd,"welcome",7,0,(struct sockaddr*)&from,len);//发送信息

25 close(sockfd);

26 return 0;

27  }

客户端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<sys/socket.h>

4 #include<netinet/in.h>

5 #include<arpa/inet.h>

6 #include<string.h>

7

8 int main(){

9  int sockfd = socket(PF_INET,SOCK_DGRAM,0);

10  if(sockfd ==  -1) perror("socket"),exit(-1);

11  struct sockaddr_in addr;

12  addr.sin_family = PF_INET;

13  addr.sin_port = htons(2222);

14  addr.sin_addr.s_addr = INADDR_ANY;

15 // write(sockfd,"hello",5);没有接收方地址

16  sendto(sockfd,"hello",5,0,(struct sockaddr*)&addr,sizeof(addr));

17  char buf[100] ={};

18 // read(sockfd,buf,100);

19  struct sockaddr_in from;

20  socklen_t len =sizeof(from);

21  recvfrom(sockfd,buf,100,0,(struct sockaddr*)&from,&len);

22  char* fromip = inet_ntoa(from.sin_addr);

23  printf("%s发来%d字节信息\n",fromip,len);

24  printf("%s\n",buf);

25  close(sockfd);

26  return 0;

27 }

时间服务器:

服务端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<sys/socket.h>

4 #include<netinet/in.h>

5 #include<arpa/inet.h>

6 #include<string.h>

7 #include<signal.h>

8 #include<time.h>

9

10 int sockfd;

11 void fa(int signo){

12   close(sockfd);

13   printf("关闭服务器成功!\n");

14   exit(-1);

15 }

16 int main(){

17   signal(SIGINT,fa);

18   int sockfd =socket(PF_INET,SOCK_DGRAM,0);

19   if(sockfd == -1) perror("socket"),exit(-1);

20   struct sockaddr_in addr;

21   addr.sin_family = PF_INET;

22   addr.sin_port = htons(2222);//端口

23   addr.sin_addr.s_addr = INADDR_ANY;//服务器IP

24   int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));//开放端口

25   if(res == -1) perror("bind"),exit(-1);

26   printf("bind ok\n");

27   while(1){

28      char buf[100] ={};

29      struct sockaddr_in from;

30      socklen_t len = sizeof(from);

31      recvfrom(sockfd,buf,100,0,(struct sockaddr*)&from,&len);

32      if(strcmp(buf,"hello")==0){

33       char ts[100]={};

34       time_t curtime = time(0);//获得当前时间秒数

35       struct tm* cur = localtime(&curtime);//将时间秒数转换成tm结构

36       sprintf(ts,"%4d-%02d-%02d  %02d:%02d:%02d",

cur->tm_year+1900,cur->tm_mon+1,cur->tm_mday,

cur->tm_hour,cur->tm_min,cur->tm_sec) ;

38       sendto(sockfd,ts,strlen(ts),0,(struct sockaddr*)&from,len);//发送

39      }

40   }

41 return 0;

42 }

客户端:

1 #include<stdio.h>

2 #include<stdlib.h>

3 #include<sys/socket.h>

4 #include<netinet/in.h>

5 #include<arpa/inet.h>

6 #include<string.h>

7

8 int main(){

9  int sockfd = socket(PF_INET,SOCK_DGRAM,0);

10  if(sockfd == -1) perror("socket"),exit(-1);

11  struct sockaddr_in addr;

12  addr.sin_family = PF_INET;

13  addr.sin_port = htons(2222);

14  addr.sin_addr.s_addr = INADDR_ANY;

15 // write(sockfd,"hello",5);没有接收方地址

16  sendto(sockfd,"hello",5,0,(struct sockaddr*)&addr,sizeof(addr));

17  char buf[100] ={};

18 // read(sockfd,buf,100);

19  struct sockaddr_in from;

20  socklen_t len =sizeof(from);

21  recvfrom(sockfd,buf,100,0,(struct sockaddr*)&from,&len);

22  char* fromip = inet_ntoa(from.sin_addr);

23  printf("%s发来%d字节信息\n",fromip,len);

24  printf("%s\n",buf);

25  close(sockfd);

26  return 0;

27 }

UC编程之网络通信(TCP/UDP)的更多相关文章

  1. 【深入浅出Linux网络编程】 “实践 -- TCP & UDP”

    通过上一篇博客的学习,你应该对基于epoll的事件触发机制有所掌握,并且通过阅读sio.c/sio.h应该也学会了如何封装epoll以及如何通过设计令epoll更加实用(用户回调,用户参数). 简单回 ...

  2. 三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

    这篇文章主要是来做(da)推(guang)介(gao)的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,后面会 ...

  3. 三十天学不会TCP,UDP/IP网络编程-IP头格式祥述

    我又来了,这篇文章还是来做(da)推(guang)介(gao)我自己的!俗话说事不过三,我觉得我下次得换个说法了,不然估计要被厌恶了,但是我是好心呐,一定要相信我纯洁的眼神.由于这两年接触到了比较多的 ...

  4. Python的网络编程[0] -> socket[0] -> socket 与 TCP / UDP

    Socket socket 简述 / socket Abstract 网络进程通信与 socket 网络中进程之间如何通信,首要解决的问题是如何唯一标识一个进程,否则通信无从谈起.在本地可以通过进程 ...

  5. 开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等

    开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等 C++开发网络通信程序时用asio是个不错的选择 ...

  6. TCP/UDP Linux网络编程详解

    本文主要记录TCP/UDP网络编程的基础知识,采用TCP/UDP实现宿主机和目标机之间的网络通信. 内容目录 1. 目标2.Linux网络编程基础2.1 嵌套字2.2 端口2.3 网络地址2.3.1 ...

  7. 网游中的网络编程系列1:UDP vs. TCP

    原文:UDP vs. TCP,作者是Glenn Fiedler,专注于游戏网络编程相关工作多年. 目录 网游中的网络编程系列1:UDP vs. TCP 网游中的网络编程2:发送和接收数据包 网游中的网 ...

  8. Java 网络编程(二) 两类传输协议:TCP UDP

    链接地址:http://www.cnblogs.com/mengdd/archive/2013/03/09/2951841.html 两类传输协议:TCP,UDP TCP TCP是Transfer C ...

  9. Windows下C语言的Socket编程例子(TCP和UDP)

    原文:Windows下C语言的Socket编程例子(TCP和UDP) 刚刚学windows编程,所以想写学习笔记,这是一个简单的Socket程序例子,开发环境是vc6: 首先是TCP server端: ...

随机推荐

  1. 用dedecms自定义表单创建简易自助预约系统

    建站往往需要根据客户的需求来增加相应的功能,比如预约.平时用比较多的是织梦系统,那么如何用dedecms自定义表单创建简易自助预约系统呢? 进入dedecms后台,左侧菜单中依次点击“核心” - 频道 ...

  2. BZOJ2435: [Noi2011]道路修建

    这种水题真是……没一次AC都不好意思见人啊 P.S. LINUX无限栈真是爽炸了… 我爱递归 /**************************************************** ...

  3. C#中“貌似”跳出while(true)死循环

    当程序第一次执行到Read()函数时,程序会被阻塞,然后输入字符,Enter之后程序被激活,windows平台会自动在输入字符之后加入回车符和换行符,此时输入流中就有三个字符,然而read每次只读取一 ...

  4. 历代诗词咏宁夏注释1----常星景:< 六盘>

    六盘 常星景 关中形势甲天下,四岳分峙西太华.[1] 中有汭泾经纬之,六盘嵚崎历历落.[2] □□□□其流亚,终年峰头雪不消. 弟畜太白兒美高,眼底培缕纷纷何足数,呼吸想通天尺五.[3] 西北堆镇一切 ...

  5. Apache POI 解析 microsoft word 图片文字都不放过

    http://blog.csdn.net/njchenyi/article/details/6894500 http://haohaoxuexi.iteye.com/blog/2031335

  6. Spring mvc json null

    http://blog.csdn.net/zdsdiablo/article/details/9429263

  7. CF 197 DIV2 Xenia and Bit Operations 线段树

    线段树!!1A 代码如下: #include<iostream> #include<cstdio> #define lson i<<1 #define rson i ...

  8. Linux网络编程6——使用TCP实现文件服务器

    需求 当客户端连接上服务器后,服务器会将相应文件传输给客户端,实现文件下载. 思路 服务器端,主进程负责listen.循环内,主进程每从任务请求队列中accept出一个请求,就fork出孙子完成文件传 ...

  9. UVA 10497 - Sweet Child Makes Trouble 高精度DP

    Children are always sweet but they can sometimes make you feel bitter. In this problem, you will see ...

  10. Protobuf动态解析那些事儿

    需求背景 在接收到 protobuf 数据之后,如何自动创建具体的 Protobuf Message 对象,再做反序列化.“自动”的意思主要有两个方面:(1)当程序中新增一个 protobuf Mes ...