网络常识

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. 编译libcore-amr静态库

    在此链接下 https://github.com/feuvan/opencore-amr-iOS 下载它的源码到本地, 然后cd到此目录下,在终端输入命令./build_ios_xcode6.sh,便 ...

  2. 亚马逊 在线测试题目 amazon

    分析:其实就是求矩形中某一个点到其他点的距离加权最小 方法一: 对每一个点求其到其他点的加权距离,然后比较最小.由于有M*N个点,对每一个点求加权距离是O(M*N)的,所以整体时间复杂度是O(M*M* ...

  3. 在centos 6.5 在virtual box 上 安装增强版工具

    centos 6.5 在virtual box 上 安装增强版工具: 出现:centos unable to find the source of your current linux kernel ...

  4. ObjectStore onFetch方法获取记录总数

    转自:http://blog.csdn.net/earthhour/article/details/38686029 ObjectStore onFetch方法获取记录总数 require(['doj ...

  5. C++时间标准库时间time和系统时间的使用

    #include <iostream> #include <time.h> #include <stdio.h> #include <windows.h> ...

  6. self._raiseerror(v) File "D:\GameDevelopment\Python27\lib\xml\etree\ElementTree.py", line 1506, in _raiseerror

    D:\BaiDuYun\Plist>python unpack_plist.py lobbyRelieveTraceback (most recent call last): File &quo ...

  7. Sqli-labs less 19

    Less-19 从源代码中我们可以看到我们获取到的是HTTP_REFERER 那和less18是基本一致的,我们从referer进行修改. 还是像less18一样,我们只给出一个示例 将referer ...

  8. PHP-Java-Bridge使用笔记,2014年9月最新版

    这是我在做平安银行开发的时候,本地使用PHP环境,平安银行接口为Java接口的时候,采用PHP-Java-Bridge的方式调用接口的笔记.因为现在网上的教程基本上都不行了,所以在这里贴出我能使用的而 ...

  9. Python - 装饰器使用过程中的误区

    曾灵敏 - APRIL 27, 2015 装饰器基本概念 大家都知道装饰器是一个很著名的设计模式,经常被用于AOP(面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,Web权限校验, C ...

  10. C#&java重学笔记(泛型)

    C#部分: 1.泛型的出现主要用于解决类.接口.委托.方法的通用性,通过定义泛型类.接口.委托.方法,可以让不同类型的数据使用相同运算规则处理数据,方便了开发. 2.利用System.Nullable ...