socket实现不同服务器上的进程间的通信。
socket是一个伪文件,分成两个部分:读缓冲区和写缓冲区。所以socket一旦建立就会在PCB中对应生成一个文件描述符fd。



socket必须成对出现。
=============================
网络字节序:
大小端:小端,低位存低地址,高位存高地址。大端相反。
总之在网络间传递的包都是大端。

网络字节序和主机字节序的转换
点分十进制转网络大端

- #include
- #include
- int main(int argc,char *argv[])
- {
- //准备转换成大端的IP地址
- char buf[]="192.168.136.101";
- unsigned int num=0;
- //转成大端
- inet_pton(AF_INET,buf,&num);
- unsigned char * p=(unsigned char *)#
- printf("%d %d %d %d\n",*p,*(p+1),*(p+2),*(p+3));
- //大端转小端
- char ip[16]="";
- printf("%s\n",inet_ntop(AF_INET,&num,ip,16));
- return 0;
- }
IPV4套接字结构体

我们需要指定的就是协议 IP 端口,将这三个东西封装成一个结构体
man 7 ip
IPV4套接字结构体
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET 协议 */
in_port_t sin_port; /* port in network byte order 端口*/
struct in_addr sin_addr; /* internet address IP地址*/
};/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
通用套接字结构体
TCP特点:出错重传,每次发送数据对方都会回ACK,可靠。
socket服务器编写
-
- #include
- #include
-
- #include
- #include
- #include
- #include
- int main(int argc, char *argv[])
- {
- //创建套接字/文件描述符
- int lfd = socket(AF_INET,SOCK_STREAM,0);
- //绑定。将协议和端口转成大端封装进结构体
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(8000);
- // addr.sin_addr.s_addr = INADDR_ANY;//绑定的是通配地址
- //此处将文件描述符绑定到本服务器的IP地址
- inet_pton(AF_INET,"192.168.136.101",&addr.sin_addr.s_addr);
- int ret = bind(lfd,(struct sockaddr *)&addr,sizeof(addr));
- if(ret < 0)
- {
- perror("");
- exit(0);
-
- }
- //监听
- listen(lfd,128);
- //提取
- struct sockaddr_in cliaddr;
- socklen_t len = sizeof(cliaddr);
- int cfd = accept(lfd,(struct sockaddr *)&cliaddr,&len);
- char ip[16]="";
- printf("new client ip=%s port=%d\n",inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr,
- ip,16), ntohs(cliaddr.sin_port));
- //读写
- char buf[1024]="";
- while(1)
- {
- bzero(buf,sizeof(buf));
- // int n = read(STDIN_FILENO,buf,sizeof(buf));
- // write(cfd,buf,n);
- int n =0;
- n = read(cfd,buf,sizeof(buf));
- if(n ==0 )//如果read返回等于0,代表对方关闭
- {
- printf("client close\n");
- break;
- }
- printf("%s\n",buf);
-
- }
- //关闭
- close(lfd);
- close(cfd);
- return 0;
- }
-
-
三次握手

多进程实现并发服务器
与线程版进行对比

gcc 02_process_tcp_server.c wrap.c
-
- #include
- #include
- #include
- #include
- #include
- #include "wrap.h"
- void free_process(int sig)
- {
- pid_t pid;
- while(1)
- {
- pid = waitpid(-1,NULL,WNOHANG);
- if(pid <=0 )//小于0 子进程全部退出了 =0没有进程没有退出
- {
- break;
- }
- else
- {
- printf("child pid =%d\n",pid);
- }
- }
-
-
-
- }
- int main(int argc, char *argv[])
- {
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set,SIGCHLD);
- sigprocmask(SIG_BLOCK,&set,NULL);
- //创建套接字,绑定
- int lfd = tcp4bind(8008,NULL);
- //监
- Listen(lfd,128);
- //提取
- //回射
- struct sockaddr_in cliaddr;
- socklen_t len = sizeof(cliaddr);
- while(1)
- {
- char ip[16]="";
- //提取连接,
- int cfd = Accept(lfd,(struct sockaddr *)&cliaddr,&len);
- printf("new client ip=%s port=%d\n",inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr,ip,16),
- ntohs(cliaddr.sin_port));
- //fork创建子进程
- pid_t pid;
- pid = fork();
- if(pid < 0)
- {
- perror("");
- exit(0);
- }
- else if(pid == 0)//子进程
- {
- //关闭lfd
- close(lfd);
- while(1)
- {
- char buf[1024]="";
-
- int n = read(cfd,buf,sizeof(buf));
- if(n < 0)
- {
- perror("");
- close(cfd);
- exit(0);
- }
- else if(n == 0)//对方关闭j
- {
- printf("client close\n");
- close(cfd);
- exit(0);
-
- }
- else
- {
- printf("%s\n",buf);
- write(cfd,buf,n);
- // exit(0);
- }
- }
-
- }
- else//父进程
- {
- close(cfd);
- //回收
- //注册信号回调
- struct sigaction act;
- act.sa_flags =0;
- act.sa_handler = free_process;
- sigemptyset(&act.sa_mask);
- sigaction(SIGCHLD,&act,NULL);
- sigprocmask(SIG_UNBLOCK,&set,NULL);
-
- }
- }
- //关闭
-
-
-
- return 0;
- }
-
-
1
2
3
线程版服务器
- #include
- #include
- #include "wrap.h"
-
- typedef struct c_info
- {
- int cfd;
- struct sockaddr_in cliaddr;
- }CINFO;
- void* client_fun(void *arg);
- int main(int argc, char *argv[]){
- if(argc<2)
- {
- printf("argc<2 >>>> \n ./a.out 8000 \n");
- return 0;
- }
- short port=atoi(argv[1]);
- int lfd=tcp4bind(port,NULL);
- Listen(lfd,128);
- struct sockaddr_in cliaddr;
- socklen_t len=sizeof(cliaddr);
- CINFO *info;
- while(1){
- int cfd=Accept(lfd,(struct sockaddr *)&cliaddr,&len);
- char ip[16]="";
- printf("new client ip =%s port=%d\n",inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr,ip,16),
- ntohs(cliaddr.sin_port)
- );
- pthread_t pthid;
- info=malloc(sizeof(CINFO));
- info->cfd=cfd;
- info->cliaddr=cliaddr;
-
- pthread_create(&pthid,NULL,client_fun,info);
- }
- return 0;
-
-
- }
-
- void* client_fun(void *arg)
- {
- CINFO *info=(CINFO *)arg;
- char ip[16]="";
-
- printf("new client ip =%s port=%d\n",inet_ntop(AF_INET,&(info->cliaddr.sin_addr.s_addr),ip,16),
- ntohs(info->cliaddr.sin_port));
- while(1)
- {
- char buf[1024]="";
- int count=0;
- count =read(info->cfd,buf,sizeof(buf));
- if(count<0)
- {
- printf("client close\n");
- break;
- }
- else if (count==0)
- {
- printf("clent close\n");
- break;
- }
- else
- {
- printf("%s\n",buf);
- write(info->cfd,buf,count);
- }
- }
- close(info->cfd);
- free(info);
- }