https://blog.csdn.net/antony1776/article/details/73717666

实现C/S程序,加上登录注册聊天等功能。

然后要做个协议的样子出来。

比如说注册功能要把用户名密码一起发送过去,然后在前面在加一个标志,表示用的是哪个操作。就相当于是一个协议。

然后下面的代码并没有实现协议。

写的很累赘,就是问来问去

struct user {
int flag;
string user;
string password;
int length;
char option[MAX_BUF_SIZE];
};

协议一般就是定义一个结构体。

服务器端:

#include<iostream>
#include<map>
#include<Winsock2.h>
#include<thread>
#include<time.h>
#include<cstdio>
#include<vector>
using namespace std;
#define MAX_CLIENT 10
#define MAX_BUF_SIZE 65535
#define UDP_SRV_PORT 2345
typedef pair<SOCKET, string> pii;
int TcpClientCount = ;
char ServerTCPBuf[MAX_BUF_SIZE];
char ServerUDPBuf[MAX_BUF_SIZE];
char tmp[MAX_BUF_SIZE];
char ServerTCPTimeBuf[];
//char getTime[256] = "GET CUR TIME";
//typedef pair<bool, string> pbs;
//map<ULONG, pbs> islogin;
struct TcpThreadParam {
SOCKET sock;
sockaddr_in addr;
};
vector<pii> onlineUser;
map<string, string> allUser;
map<string, bool> isLogin;
string realUser;
//todo : 聊天
void TCPFun(TcpThreadParam *lpParam, DWORD threadId) {
SOCKET TcpSocket = ((TcpThreadParam*)lpParam)->sock;
SOCKADDR_IN TcpClientAddr = ((TcpThreadParam*)lpParam)->addr;
sprintf(ServerTCPBuf, "%5d%s", UDP_SRV_PORT, "START");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send start error %d!\n", threadId, WSAGetLastError());
}
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "1:新用户注册\n2:用户登录\n3:发消息聊天室\n4:得到服务器时间\n5:退出请输入exit再重新选择操作\n请选择操作");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send start error %d!\n", threadId, WSAGetLastError());
}
int TCPBytesReceived;
time_t CurSysTime;
struct tm *tblock;
string user;
while(true) {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
TCPBytesReceived = recv(TcpSocket, ServerTCPBuf, sizeof(ServerTCPBuf), );
if(TCPBytesReceived == || TCPBytesReceived == SOCKET_ERROR) {
break;
}
// printf("from %d.%d.%d.%d\n", TcpClientAddr.sin_addr.S_un.S_un_b.s_b1,
// TcpClientAddr.sin_addr.S_un.S_un_b.s_b2, TcpClientAddr.sin_addr.S_un.S_un_b.s_b3,
// TcpClientAddr.sin_addr.S_un.S_un_b.s_b4);
// ULONG ipULONG = TcpClientAddr.sin_addr.S_un.S_addr;
int flag;
flag = (USHORT)atoi(ServerTCPBuf);
if(flag == ) {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "请输入用户名");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send user error %d!\n", threadId, WSAGetLastError());
}
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
TCPBytesReceived = recv(TcpSocket, ServerTCPBuf, sizeof(ServerTCPBuf), );
user = (string)ServerTCPBuf;
if(allUser.count(user)) {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "该用户名已注册,请输入exit再重新选择操作!");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send other user error %d!\n", threadId, WSAGetLastError());
}
}
else {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "请输入密码");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send password error %d!\n", threadId, WSAGetLastError());
}
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
TCPBytesReceived = recv(TcpSocket, ServerTCPBuf, sizeof(ServerTCPBuf), );
string password = (string)ServerTCPBuf;
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "注册成功,请重新选择操作");
allUser[user] = password;
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send password error %d!\n", threadId, WSAGetLastError());
}
allUser[user] = password;
}
}
else if(flag == ) {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "请输入用户名");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send user error %d!\n", threadId, WSAGetLastError());
}
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
TCPBytesReceived = recv(TcpSocket, ServerTCPBuf, sizeof(ServerTCPBuf), );
string user = (string)ServerTCPBuf;
if(!allUser.count(user)) {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "没有该用户,请输入exit再重新选择操作");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send no user error %d!\n", threadId, WSAGetLastError());
}
}
else {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "请输入密码");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send password error %d!\n", threadId, WSAGetLastError());
}
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
TCPBytesReceived = recv(TcpSocket, ServerTCPBuf, sizeof(ServerTCPBuf), );
string password = (string) ServerTCPBuf;
if(allUser[user] != password) {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "exit");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send other password error %d!\n", threadId, WSAGetLastError());
}
}
else {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "登录成功,请重新选择操作");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send error %d!\n", threadId, WSAGetLastError());
}
isLogin[user] = true;
realUser = user;
onlineUser.push_back(pii(TcpSocket, user));
}
}
}
else if(flag == ) {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
sprintf(ServerTCPBuf, "%s", "请输入内容");
if(send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), ) == SOCKET_ERROR) {
printf("thread %u send content error %d!\n", threadId, WSAGetLastError());
}
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
while(true) {
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
TCPBytesReceived = recv(TcpSocket, ServerTCPBuf, sizeof(ServerTCPBuf), );
if(strlen(ServerTCPBuf) == ) break;
if(strcmp(ServerTCPBuf, "exit") == ) {
send(TcpSocket, ServerTCPBuf, strlen(ServerTCPBuf), );
isLogin[user] = false;
break;
}
else {
printf("%s\n", ServerTCPBuf);
for(int i = ; i < onlineUser.size(); i++) {
if(onlineUser[i].first == TcpSocket || !isLogin[onlineUser[i].second]) continue;
send(onlineUser[i].first, ServerTCPBuf, strlen(ServerTCPBuf), );
}
}
}
}
else {
CurSysTime = time(NULL);
tblock = localtime(&CurSysTime);
memset(ServerTCPBuf, , sizeof(ServerTCPBuf));
strftime(ServerTCPBuf, sizeof(ServerTCPBuf), "%Y-%m-%d %H:%M:%S", tblock);
// strcpy(ServerTCPTimeBuf, asctime(tblock));
memset(ServerTCPTimeBuf, , sizeof(ServerTCPTimeBuf));
sprintf(ServerTCPTimeBuf, "%s\n%s", ServerTCPBuf, "请重新选择操作");
if(send(TcpSocket, ServerTCPTimeBuf, strlen(ServerTCPTimeBuf), ) == SOCKET_ERROR) {
printf("thread %u send time error %d!\n", threadId, WSAGetLastError());
}
}
}
closesocket(TcpSocket);
TcpClientCount--;
}
int ind;
void UDPFun(DWORD threadID) {
SOCKET UDPSrvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
char hostname[];
gethostname(hostname, sizeof(hostname));
hostent *pHostent = gethostbyname(hostname);
SOCKADDR_IN UDPSrvAddr;
memset(&UDPSrvAddr, , sizeof(SOCKADDR_IN));
UDPSrvAddr.sin_family = AF_INET;
UDPSrvAddr.sin_port = htons(UDP_SRV_PORT);
UDPSrvAddr.sin_addr = *(in_addr*)pHostent->h_addr_list[ind];
bind(UDPSrvSocket, (sockaddr*)&UDPSrvAddr, sizeof(UDPSrvAddr));
while(true) {
memset(ServerUDPBuf, , sizeof(ServerUDPBuf));
int iSockAddrLen = sizeof(sockaddr);
SOCKADDR_IN UDPClientAddr;
recvfrom(UDPSrvSocket, ServerUDPBuf, sizeof(ServerUDPBuf), ,
(sockaddr*)&UDPClientAddr, &iSockAddrLen);
iSockAddrLen = sizeof(sockaddr);
printf("ServerUDPBuf:%s\n", ServerUDPBuf);
sendto(UDPSrvSocket, ServerUDPBuf, strlen(ServerUDPBuf), ,
(sockaddr*)&UDPClientAddr, iSockAddrLen);
}
} WSADATA wsa;
int main(int argc, char **argv) {
WSAStartup(MAKEWORD(, ), &wsa);
SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ListenSocket == INVALID_SOCKET) {
printf("TCP listen socket error %d!\n", WSAGetLastError());
}
char hostname[];
gethostname(hostname, sizeof(hostname));
hostent *pHostent = gethostbyname(hostname);
SOCKADDR_IN ListenAddr;
ListenAddr.sin_family = AF_INET;
ListenAddr.sin_port = htons((USHORT)atoi(argv[]));
for(DWORD i = ; pHostent -> h_addr_list[i]; i++) {
printf ("IP address %lu:%s\n", i, inet_ntoa (*(struct in_addr*)pHostent->h_addr_list[i]));
}
scanf("%d", &ind);
ListenAddr.sin_addr = *(in_addr*) pHostent -> h_addr_list[ind];
// ListenAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(ListenSocket, (sockaddr*)&ListenAddr, sizeof(ListenAddr)) == SOCKET_ERROR) {
printf("TCP bind error %d!\n", WSAGetLastError());
}
if(listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("TCP listen error %d!\n", WSAGetLastError());
}
SOCKET TcpSocket;
SOCKADDR_IN TcpClientAddr;
DWORD dwUdpThreadId;
thread udpt(UDPFun, dwUdpThreadId);
udpt.detach();
while(true) {
int iSockAddrLen = sizeof(sockaddr);
TcpSocket = accept(ListenSocket, (sockaddr*)&TcpClientAddr, &iSockAddrLen);
if(TcpSocket == INVALID_SOCKET) {
printf("TcpSocket error %d!\n", WSAGetLastError());
}
TcpClientCount++;
if(TcpClientCount >= MAX_CLIENT) {
printf("> MAX_CLIENT\n");
closesocket(TcpSocket);
continue;
}
TcpThreadParam Param;
Param.sock = TcpSocket;
Param.addr = TcpClientAddr;
DWORD dwTcpThreadId;
thread tcpt(TCPFun, &Param, dwTcpThreadId);
tcpt.detach();
}
closesocket(ListenSocket);
WSACleanup();
return ;
}

客户端:

#include <Winsock2.h>
#include <cstdio>
#include <iostream>
#include <thread>
#define MAX_BUF_SIZE 65535 //接收发送缓冲区大小
using namespace std;
char TCPClientBuf[MAX_BUF_SIZE];
char UDPClientBuf[MAX_BUF_SIZE];
char UDPRecvBuf[MAX_BUF_SIZE];
SOCKET TCPSocket, UDPSocket;
char TCPSendBuf[MAX_BUF_SIZE];
char content[MAX_BUF_SIZE];
char getTime[] = "GET CUR TIME";
USHORT ServerUDPPort;
bool islogin = false;
char user[];
char password[];
char realUser[];
void sendMessage(SOCKET s) {
while(true) {
memset(content, , sizeof(content));
memset(TCPSendBuf, , sizeof(TCPSendBuf));
scanf("%s", content);
// printf("%s\n", content);
if(strcmp(content, "exit") != ) {
// printf("%s\n", realUser);
sprintf(TCPSendBuf, "%s:%s", realUser, content);
if(send(s, TCPSendBuf, strlen(TCPSendBuf), ) == SOCKET_ERROR) {
printf("send Message error %d\n", WSAGetLastError());
}
}
else {
if(send(s, content, strlen(content), ) == SOCKET_ERROR) {
printf("send Message error %d\n", WSAGetLastError());
}
return;
}
}
} int main(int argc, char * argv[]) {
WSADATA wsaData;
if(WSAStartup(MAKEWORD(,),&wsaData)!=) {
printf("Failed to load Winsock.\n");
return -;
}
SOCKADDR_IN TCPServer, UDPServer;
//填写要连接的服务器地址信息
TCPServer.sin_family = AF_INET;
TCPServer.sin_port = htons((USHORT)atoi(argv[]));
//inet_addr()将命令行中输入的点分IP地址转换为二进制表示的网络字节序IP地址
TCPServer.sin_addr.s_addr = inet_addr(argv[]);
//建立客户端流式套接口
TCPSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(TCPSocket == INVALID_SOCKET) {
printf("socket() Failed: %d\n",WSAGetLastError());
return -;
}
//请求与服务器端建立TCP连接
if(connect(TCPSocket,(sockaddr*)&TCPServer,sizeof(TCPServer)) == INVALID_SOCKET) {
printf("connect() Failed: %d\n", WSAGetLastError());
return -;
}
int BytesReceived;
BytesReceived = recv(TCPSocket, TCPClientBuf, sizeof(TCPClientBuf), );
if(BytesReceived < ) {
printf("UDP port recv error %d!\n", WSAGetLastError());
}
char portnum[];
memcpy(portnum, TCPClientBuf, );
ServerUDPPort = (USHORT)atoi(portnum);
printf("ServerUDPPort: %d\n", ServerUDPPort);
UDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
UDPServer.sin_family = AF_INET;
UDPServer.sin_port = htons(ServerUDPPort);
UDPServer.sin_addr.s_addr = inet_addr(argv[]);
//
if(strcmp("START", TCPClientBuf + ) != ) {
printf("%s\n", TCPClientBuf + );
return -;
}
memset(TCPClientBuf, , sizeof(TCPClientBuf));
BytesReceived = recv(TCPSocket, TCPClientBuf, sizeof(TCPClientBuf), );
printf("%s\n", TCPClientBuf);
int iSockAddrLen;
while(true) {
int UserChoice;
// sudo:输入
scanf("%d", &UserChoice);
if(UserChoice > ) continue;
memset(TCPSendBuf, , sizeof(TCPSendBuf));
sprintf(TCPSendBuf, "%d", UserChoice);
if(send(TCPSocket, TCPSendBuf, strlen(TCPSendBuf), ) == SOCKET_ERROR) {
printf("choice send error %d\n", WSAGetLastError());
}
int TCPBytesReceived;
if(UserChoice == ) {
memset(TCPSendBuf, , sizeof(TCPSendBuf));
TCPBytesReceived = recv(TCPSocket, TCPSendBuf, sizeof(TCPSendBuf), );
printf("%s\n", TCPSendBuf);
scanf("%s", user);
if(send(TCPSocket, user, strlen(user), ) == SOCKET_ERROR) {
printf("TCP send user error %d!\n", WSAGetLastError());
}
memset(TCPSendBuf, , sizeof(TCPSendBuf));
TCPBytesReceived = recv(TCPSocket, TCPSendBuf, sizeof(TCPSendBuf), );
printf("%s\n", TCPSendBuf);
scanf("%s", password);
if(strcmp(password, "exit") != ) {
if(send(TCPSocket, password, strlen(password), ) == SOCKET_ERROR) {
printf("TCP send password error %d!\n", WSAGetLastError());
}
memset(TCPSendBuf, , sizeof(TCPSendBuf));
TCPBytesReceived = recv(TCPSocket, TCPSendBuf, sizeof(TCPSendBuf), );
printf("%s\n", TCPSendBuf);
}
}
else if(UserChoice == ) {
memset(TCPSendBuf, , sizeof(TCPSendBuf));
TCPBytesReceived = recv(TCPSocket, TCPSendBuf, sizeof(TCPSendBuf), );
printf("%s\n", TCPSendBuf);
scanf("%s", user);
if(send(TCPSocket, user, strlen(user), ) == SOCKET_ERROR) {
printf("TCP send user error %d!\n", WSAGetLastError());
}
memset(TCPSendBuf, , sizeof(TCPSendBuf));
TCPBytesReceived = recv(TCPSocket, TCPSendBuf, sizeof(TCPSendBuf), );
printf("%s\n", TCPSendBuf);
scanf("%s", password);
if(strcmp(password, "exit") != ) {
if(send(TCPSocket, password, strlen(password), ) == SOCKET_ERROR) {
printf("TCP send password error %d!\n", WSAGetLastError());
}
memset(TCPSendBuf, , sizeof(TCPSendBuf));
TCPBytesReceived = recv(TCPSocket, TCPSendBuf, sizeof(TCPSendBuf), );
printf("%s\n", TCPSendBuf);
memset(TCPSendBuf, , sizeof(TCPSendBuf));
if(strcmp(TCPSendBuf, "exit") == ) {
printf("密码错误\n");
}
else {
strncpy(realUser, user, sizeof(user));
}
// memset(TCPSendBuf, 0, sizeof(TCPSendBuf));
// if(send(TCPSocket, TCPSendBuf, strlen(TCPSendBuf), 0) == SOCKET_ERROR) {
// printf("TCP send user error %d!\n", WSAGetLastError());
// }
}
}
else if(UserChoice == ) {
memset(TCPSendBuf, , sizeof(TCPSendBuf));
TCPBytesReceived = recv(TCPSocket, TCPSendBuf, sizeof(TCPSendBuf), );
printf("%s\n", TCPSendBuf);
thread t(sendMessage, TCPSocket);
t.detach();
while(true) {
memset(TCPSendBuf, , sizeof(TCPSendBuf));
TCPBytesReceived = recv(TCPSocket, TCPSendBuf, sizeof(TCPSendBuf), );
if(strcmp(TCPSendBuf, "exit") == ) break;
printf("%s\n", TCPSendBuf);
}
}
else if(UserChoice == ) {
memset(TCPSendBuf, , sizeof(TCPSendBuf));
TCPBytesReceived = recv(TCPSocket, TCPSendBuf, sizeof(TCPSendBuf), );
printf("%s\n", TCPSendBuf);
}
else if(UserChoice == ) {
closesocket(TCPSocket);
closesocket(UDPSocket);
WSACleanup();
}
}
return ;
}

C/S编程的更多相关文章

  1. 从直播编程到直播教育:LiveEdu.tv开启多元化的在线学习直播时代

    2015年9月,一个叫Livecoding.tv的网站在互联网上引起了编程界的注意.缘于Pingwest品玩的一位编辑在上网时无意中发现了这个网站,并写了一篇文章<一个比直播睡觉更奇怪的网站:直 ...

  2. JavaScript之父Brendan Eich,Clojure 创建者Rich Hickey,Python创建者Van Rossum等编程大牛对程序员的职业建议

    软件开发是现时很火的职业.据美国劳动局发布的一项统计数据显示,从2014年至2024年,美国就业市场对开发人员的需求量将增长17%,而这个增长率比起所有职业的平均需求量高出了7%.很多人年轻人会选择编 ...

  3. 读书笔记:JavaScript DOM 编程艺术(第二版)

    读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...

  4. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  5. C#异步编程(一)

    异步编程简介 前言 本人学习.Net两年有余,是第一次写博客,虽然写的很认真,当毕竟是第一次,肯定会有很多不足之处, 希望大家照顾照顾新人,有错误之处可以指出来,我会虚心接受的. 何谓异步 与同步相对 ...

  6. UE4新手之编程指南

    虚幻引擎4为程序员提供了两套工具集,可共同使用来加速开发的工作流程. 新的游戏类.Slate和Canvas用户接口元素以及编辑器功能可以使用C++语言来编写,并且在使用Visual Studio 或 ...

  7. C#与C++的发展历程第三 - C#5.0异步编程巅峰

    系列文章目录 1. C#与C++的发展历程第一 - 由C#3.0起 2. C#与C++的发展历程第二 - C#4.0再接再厉 3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰 C#5.0 ...

  8. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

  9. 关于如何提高Web服务端并发效率的异步编程技术

    最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...

  10. 异步编程 In .NET

    概述 在之前写的一篇关于async和await的前世今生的文章之后,大家似乎在async和await提高网站处理能力方面还有一些疑问,博客园本身也做了不少的尝试.今天我们再来回答一下这个问题,同时我们 ...

随机推荐

  1. @Configuration@Bean

    https://blog.csdn.net/u014199143/article/details/80692685 @Configuation等价于<Beans></Beans> ...

  2. Chrome浏览器控制台报Refused to get unsafe header "XXX"的错误

    最近在调试后端下载的接口时在浏览器的控制台中发现了红色的错误信息,例如Refused to get unsafe header "XXX":前端是采用XMLHttpRequest对 ...

  3. [CF1304D] Shortest and Longest LIS - 贪心

    看样例,>><>><,要构造 LIS 最短的,我们需要找最小链划分的方案,即包含最少的下降列 很容易想到把连续 < 的看成一段,比如样例就是 .|.|. .| ...

  4. Accept Xcode/iOS License to run git

    在没有安装Xcode的情况下, 使用了 webstorm 的git,提示 安装xcode,安装完成后,并没有打开xcode,而是再次使用git,发现 提示 输入以下命令行: sudo xcodebui ...

  5. Devxtreme 显示Master-Detail数据列表, 数据显示颜色

    ////刷新3/4簇Grid //function GetClusterGrid(id, coverageId, clusterId) { // var region = getRegionCityN ...

  6. Facebook Create Done!

    前天,又一次开了VPN,建立了自己的Facebook! Facebook我用邮箱注册的,注册邮箱在这里: acmit1966@outlook.com Facebook上我就叫做 Jack Deng 在 ...

  7. HTML页面学习

    HTML 文档结构 <!DOCTYPE html> 文档声明 <html lang="en"> 语言 <head> 网站配置信息 <met ...

  8. IDEA 在SVN上更新代码错误: Error:Server SSL certificate rejected

    在IDEA中更新代码到SVN中 ,出现了   Error:Server SSL certificate rejected    ---服务器的SSL证书  的错误 之前在网上有找过一些相关的做法,但是 ...

  9. Go_go build 和 go install

    1.作用 go build:用于测试编译包,在项目目录下生成可执行文件(有main包). go install:主要用来生成库和工具.一是编译包文件(无main包),将编译后的包文件放到 pkg 目录 ...

  10. 部署prerender服务器

    // 安装 git sudo apt-get install git sudo apt-get install curl // 请先确认服务器是否安装了curl 如果已经安装跳过即可 // 安装 no ...