Introduction to ini files
The ini file is a file with the suffix ini. It can be the initialization configuration file of the project. That is to say, after the project is released, the information in the configuration file can be modified according to the needs without modifying the project source code. The following is an example of the ini file content of my project.
You can see that there is a title [ConnectionMessage] in this ini file. There are two fields under this title. The format is field name = field value, as shown in the figure above. There can be multiple titles in the same ini file, and there can be multiple fields under each title.
Two ini file reading
C++ reading ini file
/* ::GetPrivateProfileString(title to be read, The field name in the title that needs to be read, The value to populate if the field is not present in the header, Put the obtained value into the buffer of the variable, Buffer size (consistent with the buffer size of the previous parameter), The path to the ini file (because it is in the project, you can use a relative path)); Read the data as a string, the parameter list is as above In addition:: means that the global function is called instead of its own function in the class The following is an example of reading data as an integer ::GetPrivateProfileInt(_T("ConnectionMessage"), _T("PORT"), -1, _T(".\Socket.ini")); Parameter list: title, field name, if the set value is not read, file path Return value: If found successfully, it is the value of the target field, if not found, it is the set value. In addition, if you want to write an ini file, use the following function BOOL WritePrivateProfileString( ini file title name Field name Field value (must be of CString or LPCTSTR type) ini file path ); */ CString SocketPort, ServerIP; //Declaration string ::GetPrivateProfileString(_T("ConnectionMessage"), _T("IP"), _T("Error"), ServerIP.GetBuffer(50), 50, _T(".\Socket.ini")); ::GetPrivateProfileString(_T("ConnectionMessage"), _T("PORT"), _T("Error"), SocketPort.GetBuffer(50), 50, _T(".\Socket.ini")); //::GetPrivateProfileInt(_T("ConnectionMessage"), _T("PORT"),-1, _T(".\Socket.ini")); CStringA s; s = ServerIP.GetBuffer(0); /*GetBuffer() provides a memory size that you can write to, It means to apply for a piece of memory, but it is inside the CString object. Re-modify the size of CString memory and modify the contents inside. Parameter 0 means not to apply for memory and fill the content into the original CString object*/ serverIP = s.GetBuffer(0); /*Note that I am case-sensitive, because I am S and s In addition, why is it so troublesome? Can't CString be converted directly to string? Because this is Unicode encoding, if it is multi-byte encoding, just string=CString.GetBuffer*/ s.ReleaseBuffer();//Note that after applying for resources, you must release them s=SocketPort.GetBuffer(0); serverPort = s.GetBuffer(0); s.ReleaseBuffer();
C# reads ini file
The sample ini file is populated as follows
string stationPath = @".\example.ini"; /*Add @ before the string to force escaping That is, \ is not regarded as an escape character but as a symbol. Line breaks within characters can also be accepted */ string res = ""; if (File.Exists(stationPath)) { StreamReader sr = new StreamReader(stationPath, true); //Initialize a new instance for the specified file name with the mark detection option for the specified byte order while (sr.Peek() > 0) //Peek() returns the next available character but does not use it { res = sr.ReadLine().Trim();//Because there is only one line in our ini file, only read one line and remove the following spaces } sr.Close();//Remember to close the stream } string ip=res.Split(';')[0]; string username=res.Split(';')[1]; string pwd=res.Split(';')[2]; ///Continue processing later
Three C++ Socket Communication
Server
example* Dlg = (example*)lpParamX; //I wrote a thread for communication. At the same time, if you need a pop-up box, you need the main window handle. If you don't have a thread, you can ignore the previous sentence. /*Define the sending and receiving length*/ int send_len = 0; int recv_len = 0; /*Define the send and receive buffer*/ char send_buf[200]; char recv_buf[200]; //define socket SOCKET Socket,communicationSocket; //Declare the connection information structure SOCKADDR_IN server_addr; /*Here SOCKADDR_IN SOCKADDR corresponds to sockaddr_in sockaddr respectively. */ try{ //Create socket Socket = socket(AF_INET, SOCK_STREAM, 0); if (Socket < 0) { Dlg->MessageBox(L"Failed to create socket"); return -1; } //Structure filling const char *IP = serverIP.data();//string to char* can be converted using string.data const char * portTemp = serverPort.data(); \t\t int port = atoi(portTemp); server_addr.sin_family = AF_INET; server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(port); \t\t \t\t int a=sizeof(server_addr); \t\t //bind(Socket, (SOCKADDR *) & amp;server_addr, sizeof(SOCKADDR_IN)); if (bind(Socket,(const struct sockaddr*) &server_addr,a)<0) { Dlg->MessageBox(L"Binding failed"); return -1; } if (listen(Socket, 1) < 0) { Dlg->MessageBox(L"Listening failed"); } struct sockaddr_in clientaddr; int sockLen = sizeof(struct sockaddr_in); communicationSocket = accept(Socket,(SOCKADDR *) & amp;clientaddr, & amp;sockLen); while(true) { recv_len = recv(communicationSocket, recv_buf, 200, 0); if (recv_len < 0) { continue; } else { recv_buf[recv_len] = '\0'; string s = recv_buf; CString msg; //msg.Format(L"Server information: %s",s.c_str()); //msg.Format(L"Server information:%s", CStringW(recv_buf)); //msg.Format(L"Server information:%s", CStringW(recv_buf[0])); temp = Dlg->ascll2Int(recv_buf);//This is a function I wrote myself to split the ascll string \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t ss = temp.c_str(); msg.Format(L"Client message:%s",ss); } }
Things that the server needs to pay attention to when writing Socket are as follows
1. To convert string to char*, you can use the string.data() method.
2 if(bind(Socket, (SOCKADDR *) &server_addr, sizeof(SOCKADDR_IN))<0); At first glance, there is no problem with this bind binding function, but when compiling, an error is reported, prompting that the value types on both sides of < do not match. After searching for a long time, I found that the overloading of the bind function is wrong. Although the parameters you wrote are all parameters of bind() whose return value is int, the compiler may think that you wrote another overloading. This can be placed with the mouse. Check the current bind function name to see if it is the overload we need. In order to ensure that the function overload we want is used correctly, we can declare a parameter type variable and then assign the value to the function. If we directly put the value in It may be wrong.
3 if(bind(Socket, (SOCKADDR *) & amp;server_addr, int **); The variable in the middle must be noted to have the & amp; symbol, otherwise it will prompt that the conversion cannot be performed
client
Client structure filling code server_addr.sin_family = AF_INET; server_addr.sin_addr.S_un.S_addr = inet_addr(IP); server_addr.sin_port = htons(port); int recv_len; \t\t//connect to the server if (connect(Socket, (SOCKADDR *) & amp;server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) { //Dlg->MessageBox(L"Socket connection to server failed", L"Prompt"); } else { //Dlg->MessageBox(L"Connection to server successful", L"Prompt"); recv_len = recv(communicationSocket, recv_buf, 200, 0); if (recv_len < 0) { continue; } else//Send and receive operations { recv_buf[recv_len] = '\0'; string s = recv_buf; CString msg; //msg.Format(L"Server information: %s",s.c_str()); /*The format function cannot directly convert s.c_str() into the form of L"%s" You can declare a CString outside and then assign c_str(); L"%s" in the format function can be filled with CStringW(char *) */ //msg.Format(L"Server information:%s", CStringW(recv_buf)); //msg.Format(L"Server information:%s", CStringW(recv_buf[0])); temp = Dlg->ascll2Int(recv_buf); \t\t\t\t\t //char tempChar = (char)temp[0]; \t\t\t\t\t ss = temp.c_str(); msg.Format(L"Server information:%s",ss); Dlg->messageBox(msg); } } \t\t
Four C++ ASCLL code string splitting manually implements split(char a[],char str);
Today I encountered a requirement when writing a project: the string passed in the Socket is composed of ASCLL characters.
Such as 66 55 50 51 57 48 48 54 49 44 49 52 46 48 48 48 44 50 55 50 51 46 48 48 48 44 50 53 48
B72390061,14.000,2723.000,250
The segmentation principle is as follows
//Convert the incoming ASCLL string into string, why string? Because I got it from Socket string ascll2String(char *ascll) { char *p = ascll; char tempAscllValue[50];//Determine the size yourself int j = 0; for (j = 0; j < 50; j + + ) { tempAscllValue[j] = '\0';//Initialization } int i = 0, temp; while (*p != '\0' & amp; & amp;i < 50) { if (*p == ' ')//There are spaces in the character array passed in, move it p + + ; temp = (*p - 48) * 10; p + + ; temp = temp + (*p) - 48;//Take two characters to spell the ASCLL code //tempAscllValue[i] = *p * 10 + *( + + p); tempAscllValue[i] = char(temp);//Convert the spelled ASCLL into the corresponding symbol p + + ; i + + ; } \t string s = tempAscllValue; } //Split the string according to char piHao[20], guiGe[10], theroCount[5], theroWeight[10],realWeight[10]; int i = 0,j=0,k=0,p=0,q=0,ii=0; int dataType = 0;//0-plan number 1-specification 2-theoretical weight 3-theoretical count 4-actual weight while (i < temp.length()) //Fill the array { if (temp[i] == ',') { \t\t\t\t\t\t if (dataType == 0) ii = i; i + + ; dataType + + ; \t\t\t\t\t\t continue; } if (dataType == 0) { piHao[i] = temp[i]; } else if (dataType == 1) { guiGe[j] = temp[i]; j + + ; } else if (dataType == 2) { theroWeight[k] = temp[i]; k++; } else if (dataType == 3) { theroCount[p] = temp[i]; p + + ; } else if (dataType == 4) { realWeight[q] = temp[i]; q + + ; } i + + ; } //seal guiGe[j] = '\0'; theroCount[p] = '\0'; theroWeight[k] = '\0'; realWeight[q] = '\0'; piHao[ii] = '\0';
Split the implementation and test code. Note: VS does not support the use of arr[size + 1], so I used pointers.
codeBlocks can use the above writing method, but it is not recommended to write
#include <iostream> #include<vector> using namespace std; void split(string s, char str, vector<string> & amp; stringVector); int main() { string s1 = "123;456;789;11"; cout << "s1 len=" << s1.length() << endl; string s2 = ";123;456;123"; string s3 = ";123,456;789;;"; string s4 = "1:2,3,456;789;;"; vector<string> res1, res2, res3; cout << "start" << endl; split(s1, ';', res1); split(s2, ';', res2); split(s3, ';', res3); int i = 0; cout << "******************res1******************" << endl; while (i < res1.size()) { cout << "Split number" << i << "number:" << res1[i] << endl; i + + ; } i = 0; cout << "******************res2************************" << endl; while (i < res2.size()) { cout << "Split number" << i << "number:" << res2[i] << endl; i + + ; } i = 0; cout << "******************res3**********************" << endl; while (i < res3.size()) { cout << "Split number" << i << "number:" << res3[i] << endl; i + + ; } return 0; } //String string to be split, target character, storage location after splitting void split(string s, char str, vector<string> & amp; stringVector) { int i = 0; char* start = &s[0]; char* endStr = &s[0]; while (i < s.length()) { if (s[i] == str) { int size = endStr - start; char *arr =new char[size + 1]; int j = 0; while (start != endStr)//At this time endStr==str so it is != { arr[j] = *start; j + + ; start + + ; } arr[j] = '\0'; i + + ; if (i < s.length()) { endStr + + ; start = endStr; } if (arr[0] != '\0') stringVector.push_back(arr); delete[]arr; arr = NULL; //cout<<"Split once"<<endl; } else { i + + ;//13 if (i < s.length()) endStr + + ; else//Determine whether the current endStr points to str or other characters { if (*endStr == str) { int size = endStr - start; char* arr = new char[size + 1]; int j = 0; while (start != endStr) { arr[j] = *start; j + + ; start + + ; } arr[j] = '\0'; stringVector.push_back(arr); delete[]arr; arr = NULL; } else { const int size = endStr - start; /*At this time endStr points to the last non-str character Because it also needs to exist, the length must be + 1 */ char* arr = new char[size + 2];//+ 1 again to reserve '\0' int j = 0; while (j <= size)//Cannot judge start<=endStr or start!=endStr { arr[j] = *start; j + + ; start + + ; } arr[j] = '\0'; stringVector.push_back(arr); delete[]arr; arr = NULL; } } // cout<<"Undivided"<<endl; } } }