回顾:
1。需要注意的一点:在Linux系统中,1024以下的端口只有拥有root权限的程序才能绑定,而且这些端口是给系统备用的,我们不可用。
线程
信号量,条件变量
互斥量和条件变量结合使用
socket
本地通信,网络通信
本地通信
使用socket文件进行进程间的通信
1。创建socket :int sokfd=socket(int domain,int t,0) 函数
参数1:PF_UNIX,PF_LOCAL,PF_FILE
AF_UNIX,AF_LOCAL,AF_FILE
参数2:通信方式:SOCK_STREAM 流 SOCK_DGRAM报
2。准备地址
#include <sys/un.h>
struct sockaddr_un{
xxx_family_t sun_family;//协议簇 本地:PF_UNIX类
char sun_path[];//本地通信使用的socke文件路径
};
3。绑定
bind(sockfd,(struct sockaddr*)&addr);
4.通信
其实际上就是文件的读写方式进行read/write
5。关闭
用关闭文件的方式进行关闭即可。
网络通信:
1。创建socket
int sockfd=socket{
int dom,//AF_INET,PF_INET AF_INET6/PF_INET6
int t,//SOCK_STREAM,SOCK_DGRAM
0
};
2.准备网络通信地址(IP ,端口号)
IP地址(找到计算机)/端口号(找到进程)
#include <netinet/in.h>
struct sockaddr_in {
sa_family_t sin;//AF_INET,PF_INET AF_INET6..
unsigned short sin_port;
//这个不能直接赋值,需要用htons()转换为short htonl是转换为long类型
即把主机字节和网络字节的转换。#include<arpa/inet.h>,为什么要作转换呢,因为每个主机上的int的存放有的是顺着放,有的是反着放。所以必须转换为统一的网络类型
struct in_addr sin_addr;
{
in_addr_t s_addr;//unignet int;
IP:192.168.0.23
};//为什么要用结构体来表示ip地址了。是为了方便以后ip地址升级。
inet_aton()函数可以把“192。168。0。23”转换为struct in_addr
inet_ntoa()函数可以把struct in_addr转换为“192。168。0。23”
inet_ator()函数可以把“192。168。0。23”转换为in_addr_t
};
上课
网络7层协议(实际上没有用,实际用的是tcp/ip协议)
http ftp(应用层协议) 等是基于tcp/ip协议来实现的。(底层协议)
消息包的逐层递增,每一层都包装一下。
192.168.180.53
255.255.255.0
&与运算
192.168.180.0网络地址 (找到了同一网段):数据在同一网段内是广播出去的,只是你受到了我,而我丢弃了罢了。 我可以通过特殊的方式来不丢弃(黑客)
MAC地址:网卡物理地址
网络字节顺序
主机字节顺序
--------------------
TCP与UDP通信协议方式:
他们的区别:
tcp:是面向连接的,可靠的传输协议,发出去的数据是不会丢失的。你没有收到我再给你发,没有收到我再发,直到你收到为止。因为他的通信方式是:首先要建立连接(3步握手)1。我发你2你说可以3我发落;
udp:是无连接的,不可靠的传输协议。我想跟你发信息,我不跟你握手,也不通知你。我就猛发,数据分成一个一个小包,包丢了,我也不管。你也不知道。但是效率较高。因为他无需确认
用TCP进行通信
1。创建socket int sockfd=socket(PF_INET,SOCK_STREAM,0);
sock_stream表示用tcp协议,与第三个参数没有关系。流:先到先得
2。准备地址struct sockaddr_in同之前一样的
3。邦定同之前一样
4。监听,等这别人连接我呗。
linsten(int sockfd,int backlog//排队的最大长度,10表示只有10个人可以排队,1
1人就连接不上了)即阻塞对列长度:访问量过大时候需要你排队的长度
6。等待客户端连接:
int sockfd=accept(int sockfd,struct sockaddr* addr//保存客户端地址 socklen_t *addrlen//客户端地址的长度):阻塞函数:只要服务端一执行,就等待客户端访问
返回值:可以和客户端进行通信的socket描述符
监听客户端连接、等待客户端连接
socket可分2种方式 : 1对1 、 1对多(服务器和客户端)
服务器端有多个socket来对应客户端。每当有个客户端连接上来,那个监听的s主ocket就会与之连接,然后在创建出一个socket来于这个客户端进行连接。然后再断开主socket的联系。继续监听其他客户端的连接。
7。用新的socketfd和客户端进行通信。
例子:tcpservice.c tcpclient.c
timeservice.c timeclient.c
struct tm cur_tm* = localtime(&cur);
如果每个服务都要几秒钟,多个客户端登录进来会感觉到很慢,为了使服务器能够为每个客户端同步的进行,而不是为了一个客户请求运行,导致其他客户阻塞。这样我们可以用多线程编程来解决这种感觉很慢的情况。
聊天程序:
服务器多线程:1。接收客户端的请求呗。(把客户端放到一个集合中去,只要这个集合里面有个客户端发信息过来,就把这个信息发送给每个客户端)
客户端多线程:1。输入2。接收信息
用UDP进行通信(重要的数据传输是不会使用UDP协议的)
1。创建socket
2.准备地址
3。邦定
4。通信
5。关闭
UDP相对于TCP少了几个步骤:监听,无需连接
UDP使用的是sendto来发送信息,因为UDP无需连接,直接发送就是了。sendto中有个参数,表示要发送的地址。所以send需要连接这一步骤,sendto则无需。
UDP能否知道客户端是谁呢?如何拿到呢?即如何让服务器来给客户端来发送信息怎么办呢。
接收的时候,我们使用recvfrom来接收(多了参数),这样,就知道了。而使用recv就不得而知了。
只要服务器bind就可以了。
UC结束了。查!
src源程序
bin目标文件 子目录:config.xml
lib库文件
doc文档
include要被包含的头文件
思路好了可能会先写头文件、最好把网络通信代码,和业务逻辑代码分开。可能有以下头文件:
bank.h 在里面设置一些常量,全局变量。
service.h client.h bank.h socket.h manager.h ....
配置文件的写法:
#serice configuration
server_port=10222
server_ip=192.168.0.23