struct sembuf
{
int sem_num;//下標(biāo)
int sem_op;
int sem_flg;//建議為0.
}一.信號量(同步) 1.回顧: 一個進程控制另外一個進程. 邏輯變量+pause/sleep+信號 2.信號量(semaphore)信號燈 三個數(shù)據(jù):紅燈/綠燈/黃燈 60 90 10 信號量是共享內(nèi)存整數(shù)數(shù)組.根據(jù)需要定義指定的數(shù)組長度 信號量就是根據(jù)數(shù)組中的值,決定阻塞還是解除阻塞 3.編程 3.1.創(chuàng)建或者得到信號量 semget 3.2.初始化信號量中指定下標(biāo)的值 semctl 3.3.根據(jù)信號量阻塞或者解除阻塞 semop 3.4.刪除信號量 semctl案例: A: B 創(chuàng)建信號量 得到信號量 初始化信號量 根據(jù)信號量阻塞 解除阻塞 刪除信號量 semget函數(shù)說明
int semget(key_t key,
int nums,//信號量數(shù)組個數(shù)
int flags);//信號量的創(chuàng)建標(biāo)記
//創(chuàng)建IPC_CREAT|IPC_EXCL|0666
//打開0
返回: -1:失敗 >=0:成功返回信號量的IDint semop(
int semid,//信號量ID
struct sembuf *op,//對信號量的操作.操作可以是數(shù)組多個
size_t nums,//第二個參數(shù)的個數(shù)
);
返回: -1:時失敗 0:成功 int semctl(
int semid,
int nums,
//對IPC_RMID無意義
int cmd,
//SETVAL IPC_RMID

);
//對IPC_RMID無意義 sem_op: 前提條件信號量是unsigned short int; 不能<0. -:夠減,則semop馬上返回,不夠減,則阻塞. +:執(zhí)行+操作 0:判定信號量>0,則阻塞,直到為0 控制進程的搭配方式: +(解除阻塞) -(阻塞) 0(阻塞) -(解除阻塞)#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>
//2.1.定義一個聯(lián)合體
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
main()
{
key_t key;
int semid; //信號量ID
union semun v;//2.2.定義初始化值
int r;
struct sembuf op[1];
//1.創(chuàng)建信號量
key=ftok(".",99);
if(key==-1) printf("ftok err:%m\n"),exit(-1);
//semid=semget(key,1/*信號量數(shù)組個數(shù)*/,
// IPC_CREAT|IPC_EXCL|0666);
semid=semget(key,1,0);//得到信號量
if(semid==-1) printf("get err:%m\n"),exit(-1);
printf("id:%d\n",semid);
//2.初始化信號量
v.val=2;
r=semctl(semid,0,SETVAL,v);//2.3設(shè)置信號量的值
if(r==-1) printf("初始化失敗!\n"),exit(-1);
//3.對信號量進行阻塞操作
//3.1.定義操作
op[0].sem_num=0;//信號量下標(biāo)
op[0].sem_op=-1;//信號量操作單位與類型
op[0].sem_flg=0;
while(1)
{
r=semop(semid,op,1);
printf("解除阻塞!\n");
}
//4.刪除(可以不刪除)
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>
//2.1.定義一個聯(lián)合體
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
main()
{
key_t key;
int semid; //信號量ID
union semun v;//2.2.定義初始化值
int r;
struct sembuf op[2];
//1.創(chuàng)建信號量
key=ftok(".",99);
if(key==-1) printf("ftok err:%m\n"),exit(-1);
semid=semget(key,1,0);//得到信號量
if(semid==-1) printf("get err:%m\n"),exit(-1);
printf("id:%d\n",semid);
//3.對信號量進行阻塞操作
//3.1.定義操作
op[0].sem_num=0;//信號量下標(biāo)
op[0].sem_op=1;//信號量操作單位與類型
op[0].sem_flg=0;
op[1].sem_num=0;//信號量下標(biāo)
op[1].sem_op=1;//信號量操作單位與類型
op[1].sem_flg=0;
while(1)
{
r=semop(semid,op,2);
sleep(1);
}
//4.刪除(可以不刪除)
//semctl(semid,0,IPC_RMID);
}
二.網(wǎng)絡(luò)
1.基礎(chǔ)(ip)
1.1.網(wǎng)絡(luò)工具
ping
ping ip地址
ping -b ip廣播地址
ifconfig -a
netstat -a
netstat -u
netstat -t
netstat -x
netstat -n
route
lsof
1.2.網(wǎng)絡(luò)的基本概念
網(wǎng)絡(luò)編程采用socket模型.
網(wǎng)絡(luò)通信本質(zhì)也是進程之間的IPC。
是不同主機之間。
識別主機:4字節(jié)整數(shù):IP地址
識別進程:2字節(jié)整數(shù):端口號
IP地址的表示方法: 內(nèi)部表示:4字節(jié)整數(shù)
外部表示:數(shù)點字符串
結(jié)構(gòu)體
1 2 3 4 分段表示,每個段使用.分割
"192.168.0.26"
ip地址的轉(zhuǎn)換:
struct sockaddr_in
{
int sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
}
struct in_addr
{
in_addr_t s_addr;
}
//總結(jié): IP地址的表示 字符串表示"192.168.0.26" 整數(shù)表示:in_addr_t; 字結(jié)構(gòu)表示struct in_addr; 連接點:endpoint struct sockaddr_in
{
in_port_t sin_port;
struct in_addr sin_addr;
};
1.3.IP地址的轉(zhuǎn)換 inet_addr //把字符串IP轉(zhuǎn)換為二進制整數(shù)IP(網(wǎng)絡(luò)字節(jié)序) inet_aton //把字符串IP轉(zhuǎn)換為struct in_addr;(網(wǎng)絡(luò)字結(jié)序) #inet_network//把字符串IP轉(zhuǎn)換為二進制整數(shù)IP(本地字節(jié)序) inet_ntoa //把結(jié)構(gòu)體struct in_addr轉(zhuǎn)換為字符串IP
4個本地主機字節(jié)序與網(wǎng)絡(luò)序轉(zhuǎn)換函數(shù):
h表示主機字節(jié)序,n表示網(wǎng)絡(luò)字節(jié)序,s表示兩個2字節(jié),l表示4個字節(jié)
uint16_t htons(uint16_t) uint32_t htonl(uint32_t) uint16_t ntohs(uint16_t) uint32_t ntohl(uint32_t) ps:所以發(fā)送時候,端口轉(zhuǎn)換可以用htons,而ip可以用htonl
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main()
{
/*
in_addr_t nip=192<<24 | 168 <<16 | 0<<8 | 26;
char *ip="192.168.0.26";
//把整數(shù)轉(zhuǎn)換為字符串inet_ntoa
struct in_addr sip;
int myip;
sip.s_addr=nip;
printf("nip:%u\n",nip);
printf("%s\n",inet_ntoa(sip));
myip=inet_addr(ip);
printf("%u\n",myip);
printf("%hhu.%hhu.%hhu.%hhu\n", myip>>24 & 255,
myip>>16 & 255,
myip>>8 & 255,
myip>>0 & 255);
*/
/*
char ip[4]={192,168,0,26};
printf("%d\n",*(int*)ip);
*/
char *ip="10.45.8.1";
struct in_addr addr;
in_addr_t net;
in_addr_t host;
struct in_addr tmp;
inet_aton(ip,&addr);
net=inet_lnaof(addr);
host=inet_netof(addr);
tmp.s_addr=net;
printf("%s\n",inet_ntoa(tmp));
tmp.s_addr=host;
printf("%s\n",inet_ntoa(tmp));
}
1.4.IP地址的意義 IP地址的位表達不同意義: IP地址組建網(wǎng)絡(luò):網(wǎng)絡(luò)標(biāo)識/主機標(biāo)識 網(wǎng)絡(luò) 主機 A類 7 24 網(wǎng)絡(luò)少 主機 B類 14 16 C類 21 8 D類 組播 E類 沒有使用 1.5.計算機系統(tǒng)中的網(wǎng)絡(luò)配置 /etc/hosts文件 配置IP,域名,主機名 gethostbyname gethostbyaddr /etc/protocols文件 配置系統(tǒng)支持的協(xié)議 /etc/services文件 配置服務(wù) get***by***; gethostbyname getprotobyname
#include <stdio.h>
#include <netdb.h>
main()
{
struct hostent *ent;
/*打開主機配置數(shù)據(jù)庫文件*/
sethostent(1);
while(1)
{
ent=gethostent();
if(ent==0) break;
printf("主機名:%s\t",ent->h_name);
printf("IP地址:%hhu.%hhu.%hhu.%hhu\t",
ent->h_addr[0],
ent->h_addr[1],
ent->h_addr[2],
ent->h_addr[3]);
printf("別名:%s\n",ent->h_aliases[0]);
}
endhostent();
}
#include <stdio.h>
#include <netdb.h>
main()
{
struct hostent *ent;
ent=gethostbyname("bbs.tarena.com.cn");
//printf("%s\n",ent->h_aliases[0]);
printf("%hhu.%hhu.%hhu.%hhu\n",
ent->h_addr_list[0][0],
ent->h_addr_list[0][1],
ent->h_addr_list[0][2],
ent->h_addr_list[0][3]);
}
#include <stdio.h>
#include <netdb.h>
#include <sys/utsname.h>
main()
{
struct protoent *ent;
struct utsname name;
ent=getprotobyname("tcp");
printf("%d\n",ent->p_proto);
uname(&name);
printf("%s\n",name.machine);
printf("%s\n",name.nodename);
printf("%s\n",name.sysname);
printf("%s\n",name.domainname);
}
2.TCP/UDP編程 對等模型:AF_INET SOCK_DGRAM 0:UDP C/S 模型:AF_INET SOCK_STREAM 0:TCP 2.0.網(wǎng)絡(luò)編程 ISO的7層模型: 物理層 數(shù)據(jù)鏈路層 數(shù)據(jù)鏈路層(數(shù)據(jù)物理怎么傳輸) 網(wǎng)絡(luò)層 IP層 (數(shù)據(jù)的傳輸方式) 傳輸層 傳輸層 (數(shù)據(jù)傳輸?shù)慕Y(jié)果) 會話層 應(yīng)用層 (數(shù)據(jù)傳遞的含義) 表示層 應(yīng)用層 2.1.UDP編程的數(shù)據(jù)特點 UDP采用對等模型SOCK_DGRAM socket socket:socket 綁定IP地址bind 連接目標(biāo)(可選) conncect read/recv/recvfrom 發(fā)送數(shù)據(jù) write/send/sendto 關(guān)閉close 案例: A: B 接收用戶的數(shù)據(jù) 發(fā)送數(shù)據(jù) 打印數(shù)據(jù)與發(fā)送者IP 接收數(shù)據(jù)并打印 返發(fā)一個信息
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
main()
{
int fd;//socket描述符號
struct sockaddr_in ad;//本機的IP地址
char buf[100];//接收數(shù)據(jù)緩沖
struct sockaddr_in ad_snd;//發(fā)送者IP地址
socklen_t len;//發(fā)送者IP的長度
int r;
fd=socket(AF_INET,SOCK_DGRAM,17);
if(fd==-1) printf("socket:%m\n"),exit(-1);
printf("建立socket成功!\n");
ad.sin_family=AF_INET;
ad.sin_port=htons(11111);
inet_aton("192.168.180.92",&ad.sin_addr);
r=bind(fd,(struct sockaddr*)&ad,sizeof(ad));
if(r==-1) printf("bind err:%m\n"),exit(-1);
printf("綁定成功!\n");
while(1)
{
len=sizeof(ad_snd);
r=recvfrom(fd,buf,sizeof(buf)-1,0,
(struct sockaddr*)&ad_snd,&len);
if(r>0){
buf[r]=0;
printf("發(fā)送者IP:%s,端口:%hu,數(shù)據(jù):%s\n",
inet_ntoa(ad_snd.sin_addr),
ntohs(ad_snd.sin_port),buf);
sendto(fd,"古怪!",strlen("古怪!"),0,
(struct sockaddr*)&ad_snd,sizeof(ad_snd));
}
if(r==0)
{
printf("關(guān)閉!\n");
break;
}
if(r==-1)
{
printf("網(wǎng)絡(luò)故障!\n");
break;
}
}
close(fd);
}
總結(jié): 1.問題: connect + send == sendto 2.問題: recvfrom的作用不是專門從指定IP接收 而是從任意IP接收數(shù)據(jù),返回發(fā)送數(shù)據(jù)者的IP 3.問題: 為什么要bind,bind主要目的告訴網(wǎng)絡(luò)發(fā)送數(shù)據(jù)的目標(biāo). 是否一定綁定才能發(fā)送數(shù)據(jù)? 否:只要知道你的IP與PORT,就能發(fā)送數(shù)據(jù). 4.問題: 為什么發(fā)送者沒有綁定IP與端口,他也有端口? 底層網(wǎng)絡(luò)驅(qū)動,幫我們自動生成IP與端口. 5.缺陷: 接收方不區(qū)分發(fā)送者的. send函數(shù) sendto函數(shù)int sendto(
int fd,//socket描述符號
const void *buf,//發(fā)送的數(shù)據(jù)緩沖
size_t size,//發(fā)送的數(shù)據(jù)長度
int flags,//發(fā)送方式MSG_NOWAIT MSG_OOB
const struct sockaddr *addr,//發(fā)送的目標(biāo)的IP與端口
socklen_t len//sockaddr_in的長度
);
返回: -1:發(fā)送失敗 >=0:發(fā)送的數(shù)據(jù)長度 recv函數(shù) recvfrom函數(shù) int recvfrom(
int fd,
void *buf,
size_t size,
int flags,
struct sockaddr*addr,//返回發(fā)送者IP與端口
socklen_t *len);//輸入返回IP的緩沖大小,返回實際IP的大小
2.2.TCP編程的數(shù)據(jù)特點 2.3.TCP服務(wù)器的編程 3.TCP的服務(wù)器編程模型 4.IP協(xié)議與處理(SOCK_RAW,SOCK_PACKET) 5.pcap編程 6.HTTP協(xié)議與網(wǎng)頁搜索 作業(yè): 1.重新編寫UDP網(wǎng)絡(luò)通信 2.使用gethostbyname的得到bbs.tarena.com.cn