当前位置: 首页 > 编程日记 > 正文

socket编程和并发服务器

socket这个词可以表示很多概念:

在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程“IP地址+端口号”就称为socket。

在TCP协议中,建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socket pair就唯一标识一个连接

socket本身有“插座”的意思,因此用来描述网络连接的一对一关系。

TCP/IP协议最早在BSD UNIX上实现,为TCP/IP协议设计的应用层编程接口称为socket API。

预备知识

网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分。

网络数据流同样有大端小端之分,那么如何定义网络数据流的地址呢?发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出

接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。

TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。例如UDP段格式,地址0-1是16位的源端口号,如果这个端口号是1000(0x3e8),则地址0是0x03,

地址1是0xe8,也就是先发0x03,再发0xe8,这16位在发送主机的缓冲区中也应该是低地址存0x03,高地址存0xe8。但是,如果发送主机是小端字节序的,这16位被解释成0xe803,而

不是1000。因此,发送主机把1000填到发送缓冲区之前需要做字节序的转换。同样地,接收主机如果是小端字节序的,接到16位的源端口号也要做字节序的转换。如果主机是大端字节

序的,发送和接收都不需要做转换。同理,32位的IP地址也要考虑网络字节序和主机字节序的问题。

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
h表示host,n表示network,l表示32位长整数,s表示16位短整数。
如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转
换,将参数原封不动地返回。

IP地址转换函数
早期
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);
char *inet_ntoa(struct in_addr in);
只能处理IPv4的ip地址
不可重入函数
注意参数是struct in_addr
现在
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
支持IPv4和IPv6

其中inet_pton和inet_ntop不仅可以转换IPv4的in_addr,还可以转换IPv6的in6_addr,因此函数接口是void *addrptr

sockaddr数据结构

strcut sockaddr 很多网络编程函数诞生早于IPv4协议,那时候都使用的是sockaddr结构体,为了向前兼容,现在sockaddr退化成了(void *)的作用,传递一个地址给函数

至于这个函数是sockaddr_in还是sockaddr_in6,由地址族确定,然后函数内部再强制类型转化为所需的地址类型

struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
struct sockaddr_in {
__kernel_sa_family_t sin_family; /* Address family */
__be16 sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
/* Internet address. */
struct in_addr {
__be32 s_addr;
}struct sockaddr_in6 {
unsigned short int sin6_family; /* AF_INET6 */
__be16 sin6_port; /* Transport layer port # */
__be32 sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
__u32 sin6_scope_id; /* scope id (new in RFC2553) */
};
struct in6_addr {
union {
__u8 u6_addr8[16];
__be16 u6_addr16[8];
__be32 u6_addr32[4];
} in6_u;
#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
};
#define UNIX_PATH_MAX 108
struct sockaddr_un {
__kernel_sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};

Pv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位端口号和32位IP地址,
IPv6地址用sockaddr_in6结构体表示,包括16位端口号、128位IP地址和一些控制字段。UNIX Domain Socket的地址格式定义在sys/un.h中,用sockaddr_un结构体表示。各种socket地址结构体的开头都是相同的,前16位表示整个结构体的长度(并不是所有UNIX的实现都有长度字段,如Linux就没有),后16位表示地址类型。
IPv4、IPv6和Unix Domain Socket的地址类型分别定义为常数AF_INET、AF_INET6、AF_UNIX。
这样,只要取得某种sockaddr结构体的首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容。
因此,socket API可以接受各种类型的sockaddr结构体指针做参数,例如bind、accept、connect等函数,
这些函数的参数应该设计成void *类型以便接受各种类型的指针,但是sock API的实现早于ANSI C标准化,那时还没有void *类型,因此这些函数的参数都用
struct sockaddr *类型表示,在传递参数之前强制类型转换一下,例如:

struct sockaddr_in servaddr;
/* initialize servaddr */
bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));

网络套接字函数

socket

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
domain:
AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址
AF_INET6 与上面类似,不过是来用IPv6的地址
AF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用
type:
SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类
型,这个socket是使用TCP来进行传输。
SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
SOCK_SEQPACKET 这个协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的
接受才能进行读取。
SOCK_RAW 这个socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使
用该协议)
SOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数
据包的顺序
protocol:
0 默认协议
返回值:
成功返回一个新的文件描述符,失败返回-1,设置errno

socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描
述符,应用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调
用出错则返回-1。对于IPv4,domain参数指定为AF_INET。对于TCP协议,type参数指定为
SOCK_STREAM,表示面向流的传输协议。如果是UDP协议,则type参数指定为SOCK_DGRAM,
表示面向数据报的传输协议。protocol参数的介绍从略,指定为0即可。

bind

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:
socket文件描述符
addr:
构造出IP地址加端口号
addrlen:
sizeof(addr)长度
返回值:
成功返回0,失败返回-1, 设置errno

服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序
的地址和端口号后就可以向服务器发起连接,因此服务器需要调用bind绑定一个固定的网络
地址和端口号。
bind()的作用是将参数sockfd和addr绑定在一起,使sockfd这个用于网络通讯的文件
描述符监听addr所描述的地址和端口号。前面讲过,struct sockaddr *是一个通用指针类
型,addr参数实际上可以接受多种协议的sockaddr结构体,而它们的长度各不相同,所以需
要第三个参数addrlen指定结构体的长度。如:

struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(8000);

首先将整个结构体清零,然后设置地址类型为AF_INET,网络地址为INADDR_ANY,这个
宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,
这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪
个IP地址,端口号为8000。

 

listen

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
sockfd:
socket文件描述符
backlog:
排队建立3次握手队列和刚刚建立3次握手队列的链接数和

查看系统默认backlog

cat /proc/sys/net/ipv4/tcp_max_syn_backlog

典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的
accept()返回并接受这个连接,如果有大量的客户端发起连接而服务器来不及处理,尚未
accept的客户端就处于连接等待状态,listen()声明sockfd处于监听状态,并且最多允许有
backlog个客户端处于连接待状态,如果接收到更多的连接请求就忽略。listen()成功返回
0,失败返回-1。

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockdf:
socket文件描述符
addr:
传出参数,返回链接客户端地址信息,含IP地址和端口号
addrlen:
传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结
返回值:
成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno

三方握手完成后,服务器调用accept()接受连接,如果服务器调用accept()时还没有
客户端的连接请求,就阻塞等待直到有客户端连接上来。addr是一个传出参数,accept()
返回时传出客户端的地址和端口号。addrlen参数是一个传入传出参数(value-result
argument),传入的是调用者提供的缓冲区addr的长度以避免缓冲区溢出问题,传出的是客
户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区)。如果给addr参数传
NULL,表示不关心客户端的地址。
我们的服务器程序结构是这样的:

 

while (1) {
cliaddr_len = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
n = read(connfd, buf, MAXLINE);
......
close(connfd);
}

整个是一个while死循环,每次循环处理一个客户端连接。由于cliaddr_len是传入传出
参数,每次调用accept()之前应该重新赋初值。accept()的参数listenfd是先前的监听文件

描述符,而accept()的返回值是另外一个文件描述符connfd,之后与客户端之间就通过这个
connfd通讯,最后关闭connfd断开连接,而不关闭listenfd,再次回到循环开头listenfd仍
然用作accept的参数。accept()成功返回一个文件描述符,出错返回-1

connect

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockdf:
socket文件描述符
addr:
传入参数,指定服务器端地址信息,含IP地址和端口号
addrlen:
传入参数,传入sizeof(addr)大小
返回值:
成功返回0,失败返回-1,设置errno

server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>#define SERV_PORT 8000int main(void)
{int sfd, cfd;int i, len;struct sockaddr_in serv_addr, client_addr;char buf[4096], client_ip[128];socklen_t addr_len;//AF_INET:ipv4   SOCK_STREAM:流协议   0:默认协议(tcp,udp)sfd = socket(AF_INET, SOCK_STREAM, 0);//绑定前先构造出服务器地址bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;//网络字节序serv_addr.sin_port = htons(SERV_PORT);//INADDR_ANY主机所有ipserv_addr.sin_addr.s_addr = htonl(INADDR_ANY);bind(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));//服务器能接收并发链接的能力listen(sfd, 128);printf("wait for connect ...\n");addr_len = sizeof(client_addr);//阻塞,等待客户端链接,成功则返回新的文件描述符,用于和客户端通信cfd = accept(sfd, (struct sockaddr *)&client_addr, &addr_len);printf("client IP:%s\t%d\n", inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, client_ip, sizeof(client_ip)),ntohs(client_addr.sin_port));while (1) {//阻塞接收客户端数据len = read(cfd, buf, sizeof(buf));write(STDOUT_FILENO, buf, len);//处理业务for (i = 0; i < len; i++)buf[i] = toupper(buf[i]);//返回给客户端结果
        write(cfd, buf, len);}close(cfd);close(sfd);return 0;
}

client

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>#define SERV_PORT 8000int main(int argc, char *argv[])
{int sfd, len;struct sockaddr_in serv_addr;char buf[4096];if (argc < 2) {printf("./client serv_ip\n");return 1;}sfd = socket(AF_INET, SOCK_STREAM, 0);bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(SERV_PORT);inet_pton(AF_INET, argv[1], &serv_addr.sin_addr.s_addr);connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));while (fgets(buf, sizeof(buf), stdin)) {write(sfd, buf, strlen(buf));len = read(sfd, buf, sizeof(buf));write(STDOUT_FILENO, buf, len);}return 0;
}

 

多进程并发服务器

#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>void perr_exit(const char *s)
{perror(s);exit(1);
}int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
{int n;again:if ( (n = accept(fd, sa, salenptr)) < 0) {if ((errno == ECONNABORTED) || (errno == EINTR))goto again;elseperr_exit("accept error");}return n;
}void Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{if (bind(fd, sa, salen) < 0)perr_exit("bind error");
}void Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{if (connect(fd, sa, salen) < 0)perr_exit("connect error");
}void Listen(int fd, int backlog)
{if (listen(fd, backlog) < 0)perr_exit("listen error");
}int Socket(int family, int type, int protocol)
{int n;if ( (n = socket(family, type, protocol)) < 0)perr_exit("socket error");return n;
}ssize_t Read(int fd, void *ptr, size_t nbytes)
{ssize_t n;again:if ( (n = read(fd, ptr, nbytes)) == -1) {if (errno == EINTR)goto again;elsereturn -1;}return n;
}ssize_t Write(int fd, const void *ptr, size_t nbytes)
{ssize_t n;again:if ( (n = write(fd, ptr, nbytes)) == -1) {if (errno == EINTR)goto again;elsereturn -1;}return n;
}void Close(int fd)
{if (close(fd) == -1)perr_exit("close error");
}
ssize_t Readn(int fd, void *vptr, size_t n)
{size_t  nleft;ssize_t nread;char   *ptr;ptr = vptr;nleft = n;while (nleft > 0) {if ( (nread = read(fd, ptr, nleft)) < 0) {if (errno == EINTR)nread = 0;elsereturn -1;} else if (nread == 0)break;nleft -= nread;ptr += nread;}return n - nleft;
}ssize_t Writen(int fd, const void *vptr, size_t n)
{size_t nleft;ssize_t nwritten;const char *ptr;ptr = vptr;nleft = n;while (nleft > 0) {if ( (nwritten = write(fd, ptr, nleft)) <= 0) {if (nwritten < 0 && errno == EINTR)nwritten = 0;elsereturn -1;}nleft -= nwritten;ptr += nwritten;}return n;
}
static ssize_t my_read(int fd, char *ptr)
{static int read_cnt;static char *read_ptr;static char read_buf[100];if (read_cnt <= 0) {
again:if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {if (errno == EINTR)goto again;return -1;} else if (read_cnt == 0)return 0;read_ptr = read_buf;}read_cnt--;*ptr = *read_ptr++;return 1;
}ssize_t Readline(int fd, void *vptr, size_t maxlen)
{ssize_t n, rc;char    c, *ptr;ptr = vptr;for (n = 1; n < maxlen; n++) {if ( (rc = my_read(fd, &c)) == 1) {*ptr++ = c;if (c  == '\n')break;} else if (rc == 0) {*ptr = 0;return n - 1;} elsereturn -1;}*ptr  = 0;return n;
}
wrap.c
#ifndef __WRAP_H_
#define __WRAP_H_void perr_exit(const char *s);
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
void Bind(int fd, const struct sockaddr *sa, socklen_t salen);
void Connect(int fd, const struct sockaddr *sa, socklen_t salen);
void Listen(int fd, int backlog);
int Socket(int family, int type, int protocol);
ssize_t Read(int fd, void *ptr, size_t nbytes);
ssize_t Write(int fd, const void *ptr, size_t nbytes);
void Close(int fd);
ssize_t Readn(int fd, void *vptr, size_t n);
ssize_t Writen(int fd, const void *vptr, size_t n);
static ssize_t my_read(int fd, char *ptr);
ssize_t Readline(int fd, void *vptr, size_t maxlen);#endif
wrap.h
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>#include "wrap.h"#define SERV_PORT 8000void do_sig(int num)
{while (waitpid(0, NULL, WNOHANG) > 0);
}
int main(int argc, char *argv[])
{int lfd, cfd, len, i;int serv_port = SERV_PORT;char buf[1024], client_ip[128];struct sockaddr_in serv_addr, client_addr;socklen_t client_len;pid_t pid;struct sigaction act;act.sa_handler = do_sig;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGCHLD, &act, NULL);if (argc == 2) serv_port = atoi(argv[1]);lfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons((short)serv_port);serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);Bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));Listen(lfd, 128);printf("wait for connect...\n");while (1) {client_len = sizeof(client_addr);cfd = Accept(lfd, (struct sockaddr *)&client_addr, &client_len);printf("client:%s\t%d\n",inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, client_ip, sizeof(client_ip)),ntohs(client_addr.sin_port));pid = fork();if (pid == 0) {//in child 
            Close(lfd);while (1) {len = Read(cfd, buf, sizeof(buf));if (len <= 0)break;Write(STDOUT_FILENO, buf, len);for (i = 0; i < len; ++i)buf[i] = toupper(buf[i]);Write(cfd, buf, len);}Close(cfd);return 0;} else if (pid > 0) {//in parent
            Close(cfd);} else {perror("fork");exit(1);}}Close(lfd);return 0;
}

客户端

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>#define SERV_PORT 8000int main(int argc, char *argv[])
{int sfd, len;struct sockaddr_in serv_addr;char buf[4096];if (argc < 2) {printf("./client serv_ip\n");return 1;}sfd = socket(AF_INET, SOCK_STREAM, 0);bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(SERV_PORT);inet_pton(AF_INET, argv[1], &serv_addr.sin_addr.s_addr);connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));while (fgets(buf, sizeof(buf), stdin)) {write(sfd, buf, strlen(buf));len = read(sfd, buf, sizeof(buf));write(STDOUT_FILENO, buf, len);}return 0;
}

多线程并发服务器

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>#include "wrap.h"#define SERV_PORT 8000void *do_work(void *arg)
{char buf[1024];int len, i;int cfd = (int)arg;pthread_detach(pthread_self());while (1) {len = Read(cfd, buf, sizeof(buf));if (len <= 0)break;Write(STDOUT_FILENO, buf, len);for (i = 0; i < len; ++i)buf[i] = toupper(buf[i]);Write(cfd, buf, len);}Close(cfd);return 0;
}int main(int argc, char *argv[])
{int lfd, cfd;int serv_port = SERV_PORT;char client_ip[128];struct sockaddr_in serv_addr, client_addr;socklen_t client_len;pthread_t tid;if (argc == 2) serv_port = atoi(argv[1]);lfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons((short)serv_port);serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);Bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));Listen(lfd, 128);printf("wait for connect...\n");while (1) {client_len = sizeof(client_addr);cfd = Accept(lfd, (struct sockaddr *)&client_addr, &client_len);printf("client:%s\t%d\n",inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, client_ip, sizeof(client_ip)),ntohs(client_addr.sin_port));pthread_create(&tid, NULL, do_work, (void *)cfd);}return 0;
}

多路I/O复用

select服务器

poll服务器

epoll服务器



转载于:https://www.cnblogs.com/xiangtingshen/p/10909231.html

相关文章:

基于协同过滤算法实现选课推荐系统

新版本教务管理系统 教务管理系统 选课功能1.系统功能 1、用户账户管理 2、学生个人信息的查看与修改 3、学生的网上选课与课程的评分 4、教师个人信息的查看与修改 5、教师对学生课程评价结果的查看 6、管理员对学生信息与教师信息的查看与添加 7、管理员对课程的增删改查 8、…

linux access函数判断文件存取权限

access&#xff08;判断是否具有存取文件的权限&#xff09;相关函数 stat&#xff0c;open&#xff0c;chmod&#xff0c;chown&#xff0c;setuid&#xff0c;setgid表头文件 #include<unistd.h>定义函数 int access(const char * pathname,int mode);函数说明 access(…

Python天天美味(35) - 细品lambda

lambda函数也叫匿名函数&#xff0c;即&#xff0c;函数没有具体的名称。先来看一个最简单例子&#xff1a; deff(x): returnx**2printf(4)Python中使用lambda的话&#xff0c;写成这样 g lambdax : x**2printg(4)lambda表达式在很多编程语言都有对应的实现。比如C#&#x…

jvm:分析工具

bin/jvisualvm.exe 可查看类实例数 bin/jconsole.exe 监控线程&#xff0c;堆&#xff0c;等 http://blog.csdn.net/yaowj2/article/details/7107818 https://blog.csdn.net/janekeyzheng/article/details/41075791 转载于:https://www.cnblogs.com/chen-msg/p/8275299.html

Django 路由分发

Django 路由分发 当一个url请求过来之后1、先到项目主目录下的urls内。2、由这个url做处理分发给其他app内的urls。 一级路由&#xff1a;主目录urls内引入include from django.conf.urls import url,include urlpatterns [# 指定分发的app目录名称url(r^cmdb/,include("…

NHibernate从入门到精通系列(7)——多对一关联映射

内容摘要 多对一关联映射概括 多对一关联映射插入和查询 多对一关联映配置介绍 一、多对一关联映射概括 关联关系是实体类与实体类之间的结构关系&#xff0c;分别为“多对一”、“一对一”、“多对多”。然而“多对一”是怎样描述的呢&#xff1f;让我们参考图1.1所示&#xf…

PLSQ执行同样的sql,使用mybatis进行动态拼装执行的时候非常慢的问题解决

如题&#xff0c;项目中碰到了同样的sql&#xff0c;在plsql中执行很快&#xff0c;几乎秒出&#xff0c;但在程序中使用mybatis框架时&#xff0c;却非常的慢&#xff0c;前提是动态拼装的sql。在使用写死的参数&#xff0c;不会出现很慢的效果。最后发现是使用 #{xxx} 去注入…

雨林木风爱好者GHOSTXP装机版_NTFS_SP3_2010_03

系统简介:系统下载参考地址:http://www.51ghostxp.cn/winxp/230.htm迅雷地址:thunder://QUFodHRwOi8vZG93bjUuZ2hvc3QyLmNuL0dIT1NUWFBfU1AzeWxtZmFpaGFvemhlXzIwMTBfMDNbTlRGU10uaXNvWlo雨林木风爱好者GHOSTXP装机版_NTFS_SP3_2010_03主要特点&#xff1a; 此系统采用硬盘安装…

栈和堆的区别(转 知乎)

①管理方式&#xff1a;栈由编译器自动管理&#xff1b;堆由程序员控制&#xff0c;使用方便&#xff0c;但易产生内存泄露。 ②生长方向&#xff1a;栈向低地址扩展(即”向下生长”)&#xff0c;是连续的内存区域&#xff1b;堆向高地址扩展(即”向上生长”)&#xff0c;是不连…

到这个年纪为什么我还要开始学习理解参与区块链?

【顺势而为&#xff0c;与时俱进的需要】看来我对信息的敏感程度还不够&#xff0c;最近才认真研读了相关文件&#xff1a;国务院关于印发“十三五”国家信息化规划的通知国发〔2016〕73号1信息技术创新代际周期大幅缩短&#xff0c;创新活力、集聚效应和应用潜能裂变式释放&am…

JavaScript小记

项目进行中需求变化&#xff0c;把所有的图片的呈现出渐出效果&#xff0c;我首先想到了filters&#xff1a;滤镜&#xff0c; <html><head> </head> <script language"JavaScript">function picload(){img.filters.revealTrans.apply()im…

Ant Design of Vue —— setFieldsValue方法 动态操作Switch组件

在开发中经常使用Form组件管理表单&#xff0c;这次想通过form提供的setFieldsValue()方法动态改变Switch组件状态&#xff0c;却没有生效。 加入valuePropName属性之后&#xff0c;就可以使用动态操作Switch组件了。 <a-switch v-decorator"[haveChildren, { valuePro…

打印机的大小设置

procedure SetPrinterPaper(APaperNo: Integer; APaperWidth, APaperHeight: Double); //设置当前打印机的纸张大小 //纸张号 &#xff19; A4 13 B5 //页宽和页高&#xff0c;单位mm var Device: array[0..255] of char; Driver: array[0..255] of char; Port: array[0..255]…

C# 对ListT取交集、连集及差集

實際演練 ※本文使用int為例&#xff0c;若為使用自訂之DataModel&#xff0c;需實作IEquatable<T>介面才能使用 1. 取交集 (A和B都有) List A : { 1 , 2 , 3 , 5 , 9 } List B : { 4 , 3 , 9 } var intersectedList list1.Intersect(list2);結果 : { 3 , 9 } 判断A和B…

面试前赶紧看了5道Python Web面试题,Python面试题No17

目录 本面试题题库&#xff0c;由公号&#xff1a;非本科程序员 整理发布第1题&#xff1a; Flask中的请求上下文和应用上下文是什么?第2题&#xff1a;django中间件的使用&#xff1f;第3题&#xff1a; django开发中数据做过什么优化&#xff1f;第4题&#xff1a; 解释一下…

最好的程序界面就是用户无需去阅读操作手册就知道该如何使用的界面

最好的程序界面就是用户无需去阅读操作手册就知道该如何使用的界面。 原则 1.一致性 如果你可以在一个列表的项目上双击后能 够弹出对话框&#xff0c;那么应该在任何列表中双击都能弹出对话框。要有统一的字体写号、统一的色调、统一的提示用词、窗口在统一的位置、按钮也在窗…

Ant Design Vue中a-select组件下拉列表在局部滚动时不跟随问题解决方法

问题如下&#xff1a; 修改方法如下 <a-tree-select:getPopupContainer"triggerNode > {return triggerNode.parentNode || document.body;}"style"width: 100%":dropdownStyle"{ maxHeight: 400px, overflow: auto }":treeData"tree…

ospf路由汇总的目的

ospf路由汇总的目的减少网络中lsa传输的数量&#xff0c;减少网络中的变化&#xff0c;减少链路状态数据库&#xff0c;减少路由表&#xff0c;大大提高数据包查表转发的能力&#xff0c;能减少因为链路状态数据库的变化而引起的spf算法的重计算。转载于:https://blog.51cto.co…

第九周学习笔记

聚合&#xff1a; 1.当聚集函数遇到空值时&#xff0c;除COUNT(*)外&#xff0c;都跳过空值而出处理非空值。 2.WHERE子句中不能使用聚集函数。 3.聚集函数只能用于SELECT和GROUP BY中的HAVING语句。 常用的聚合函数 1 count 2 sum 3 avg 4 max 5 min 使…

2019年5月26日

距离考核结束的时间只剩下5天了&#xff0c;一个特别大的问题就是前后端的交流问题&#xff0c;不单单是项目的进度&#xff0c;更多的是人与人之间的交流。页面的进度完成了一整个流程&#xff0c;剩下的就是和后端的进行交互&#xff0c;后端的进度有点慢&#xff0c;导致我现…

Django3.0 +Python3 连接mysql遇到django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer

使用idea 创建了一个Django项目&#xff0c;不想使用默认的数据库进行操作&#xff0c;想切换成mysql数据&#xff0c;在此遇到了一些问题特此记录。 按照网上所说使用pymysql进行数据库连接操作&#xff0c;安装并且配置完毕后&#xff0c;在执行数据迁移操作时报错 django.…

栈的push、pop序列

题目&#xff1a;输入两个整数序列。其中一个序列表示栈的push顺序&#xff0c;判断另一个序列有没有可能是对应的pop顺序。为了简单起见&#xff0c;我们假设push序列的任意两个整数都是不相等的。 比如输入的push序列是1、2、3、4、5&#xff0c;那么4、5、3、2、1就有可能是…

const常对象成员与常成员函数

#include <iostream>#include <string>using namespace std;class pt{public:   pt(int a,int b){this->xa,this->yb;}   int getX() const {return this->x;} //此处必须加const&#xff08;关键&#xff09;&#xff0c;否则A.getX()将无法正常调用…

根据CPU核数合理设置线程池大小

一般来说池中总线程数是核心池线程数量两倍&#xff0c;只要确保当核心池有线程停止时&#xff0c;核心池外能有线程进入核心池即可。 我们所需要关心的主要是核心池线程的数量该如何设置。 自定义线程池代码 package com.lc.concurrent; import java.util.concurrent.ArrayB…

云答题微信小程序 实现 前端加后台管理

1.为什么要使用微信云开发 微信云开发自己是不需要域名&#xff08;备案的域名&#xff09;&#xff0c;服务器&#xff0c;搭建数据库等。 2.使用技术 微信小程序相关云接口java &#xff08;SpringBootMaven&#xff09;后台管理使用 VUE 3.实现微信小程序效果如下 微信小…

用Windows Media Player截图的方法

视频截图方法&#xff1a; 关闭“视频加速功能即可”。 以Windows Media Player 9.0为例&#xff0c;选择菜单“工具→选项”&#xff0c;找到“性能”选项卡中的“视频加速”一栏&#xff0c;然后拖动下方的拉杆将默认的“完成”改为“无”&#xff0c;按“确定”保存设置&…

基于OHCI的USB主机 —— 结束语

从去年11月份开始连载的《基于OHCI的USB主机》系列总算告一段落了&#xff0c;到UFI命令层为止&#xff0c;所有USB主机的底层处理就结束了&#xff0c;再上面就是磁盘读写、文件系统、文件读写和应用系统了。这些上层应用基本上是与USB主机没有什么关系的&#xff0c;我的这个…

mac os x 查看网络端口情况

查看端口是否打开 使用 netstat 命令 a. netstat -nat | grep <端口号> , 如命令 netstat -nat | grep 3306 b. netstat -nat |grep LISTEN 使用 lsof 命令 # yongfu-pro at yongfu-pro.local in ~ [22:39:32] $ lsof -n -P -i TCP -s TCP:LISTEN COMMAND PID USER FD …

POJ1149-PIGS

1&#xff0c;从各个顾客到汇点各有一条边&#xff0c;容量就是各个顾客能买的数量上限。 2&#xff0c;在某一轮中&#xff0c;从该顾客打开的所有猪圈都有一条边连向该顾客&#xff0c;容量都是∞。 3&#xff0c;最后一轮除外&#xff0c;从每一轮的i号猪圈都有一条边连向下…

Center OS 离线安装Mysql5.7

1.相关资料准备 1.离线安装包下载 或者百度网盘 链接&#xff1a;https://pan.baidu.com/s/1oVP3u8GSaavxoJqKnvZPKg 提取码&#xff1a;vw88 2.libao库文件下载 链接&#xff1a;https://pan.baidu.com/s/12hrQIEF3kk2h2HlWE41G7w 提取码&#xff1a;fvt8 2.开始安装 检…