Don't say much nonsense, first.
To get to the point: recently Idle bored, remembered in second day when using VB to write a LAN multiplayer chat room. At that time using the Winsock, and then write out for the students to use information classes, in fact, there is no use AH .
It was a whim this afternoon to implement this function in C + +. To Baidu a bit of relevant information, just found that C + + socket is really trouble ... ( Maybe I was too much ) so I started to study very seriously (Copy). Looking for a long time did not find the template to meet my meaning, and suddenly found that if more than one person chatting online, it seems to be more threads,,???,,。 So I began to study very seriously (say, is really starting to learn). Specific socket principle please point me
After an afternoon of study (Copy), I finally have a general understanding of how the socket works, as well as the general idea of the whole communication program. (Quote the original of a big guy's blog Ε=ε=ε=┏ (゜ロ゜;) ┛)
We program should first determine what you need to implement the "method", such as the set of port number in socket socket, the setting of IP address, the setting of blocking mode, the listening and receiving of other clients, and the setting and feedback of various error messages. And in the network programming multi-person chat room coding process, I after many attempts and summarizes, has developed a general idea-namely first encapsulates socket socket, then logically encapsulates other functional classes.
But I've been doing it for a long time ... Let me summarize the problems I have encountered.
The first is the problem of compiling. Although I used to be VC, but this time I am using dev-c++ to open the project. So in the compile time encountered a few magical problems. After browsing a few big-brother's blog, found that dev-c++ to configure the compilation parameters themselves. To summarize, if you want to use the Winsock.h, you need to add in the linker -lwsock32
to use (in the project properties, the parameters, such as the linker). There is also a problem, that is, with the thread, you need to add in the compilation parameters -std=c++11
, otherwise it will compile errors. (Use VC's please automatically ignore the above paragraph)
Then put a code on it ... Please forgive me for not writing well ('? ') )
Server header file (Server.h)
#define _WINSOCK_DEPRECATED_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS#ifndef _H_H_#define _H_H_#include <thread>#include <iostream>#include <string>#include <WinSock2.h>#include <stdlib.h>#pragma comment(lib,"ws2_32.lib")using namespace std;static struct MyStruct{ SOCKET sock; int empt;}soc[4];class Server{public: Server(); ~Server(); static void Work(int id);private: SOCKET s;};#endif
Service side (Server.cpp)
#include "Server.h" Server::server () {wsadata wsadata; WORD v = Makeword (2, 2); if (:: WSAStartup (V, &wsadata) <0) {cout<< "Failed to start server!" <<endl; System ("pause"); Exit (0);} s = socket (af_inet, sock_stream, ipproto_tcp); Sockaddr_in sin; sin.sin_family = af_inet; The server listens on the port and its own IP Sin.sin_port = htons (13574); Sin.sin_addr. S_un. S_ADDR = inet_addr ("127.0.0.1"); if (:: Bind (S, (lpsockaddr) &sin,sizeof (sin)) ==socket_error) return; if (:: Listen (s,5) ==socket_error) return; cout<< "The server has been started!" <<endl; while (true) {int i; for (i=0; i<100; i++) if (soc[i].empt==0) {soc[i].empt = 1; Sockaddr_in re; int n = sizeof (re); Soc[i].sock =:: Accept (S, (sockaddr*) &re,&n); if (Soc[i].sock==invalid_socket) return; cout<< "New client =" <<soc[i].sock<<endl; Std::thread T (work,i); T.detach (); } closesocket (s);} SerVer::~server () {:: WSACleanup ();} void server::work (int id) {char msg[] = "Server = =" welcome! Press [ESC] to edit your a message, then press [Enter] to send! ";:: Send (Soc[id].sock,msg,strlen (MSG), 0); while (true) {char buff[1024]; int NR =:: recv (Soc[id].sock, Buff, 1025, 0); if (nr>0) {Buff[nr] = ' + '; cout<< "Received:" <<buff<< "(ID:" <<soc[id].sock<< ")" <<endl; for (int i=0; i<100; i++) if (soc[i].empt):: Send (Soc[i].sock,buff,strlen (buff), 0); } else {cout<< "Client = =" <<soc[id].sock<< "logout!" <<endl; Closesocket (Soc[id].sock); soc[id].empt = 0; Return }}}int Main () {server server; return 0;}
Next to the client (Client.cpp)
#include <iostream> #include <WinSock2.h> #include <thread> #include <string> #include < stdio.h> #include <stdlib.h> #include "TextColor.h" #define Key_down (Vk_noname) (Getasynckeystate (vk_noname ) & 0x8000)? 1:0) #pragma comment (lib, "Ws2_32.lib") using namespace std; SOCKET s;int Status=0;char name[100000],myip[100];void getmessege () {char buff[1024]; while (true) {int nR = recv (s,buff,1025,0), while (Status); if (nr>0) {Buff[nr] = ' + '; cout<<blue<<buff<<white<<endl; } else if (nr<0) break; }}bool getlocalip (char* IP) {wsadata wsadata; int Ret=wsastartup (Makeword (2,2), &wsadata); if (ret!=0) return false; Char hostname[256]; Ret=gethostname (HOSTNAME,SIZEOF (hostname)); if (Ret==socket_error) return false; hostent* Host=gethostbyname (hostname); if (host==null) return false; strcpy (Ip,inet_ntoa (* (in_addr*) *host->h_addr_list)); return true;} int main () {if (! Getlocalip (MyIP)) {cout<<red<< "Unknow error!" <<endl; System ("pause"); return 0;} Wsadata Wsadata; WORD V=makeword (2, 2); if (:: WSAStartup (V,&wsadata) <0) {cout<<red<< "Unknow error!" <<endl; System ("pause"); return 0;} s = socket (af_inet, sock_stream, ipproto_tcp); Sockaddr_in sin; sin.sin_family = af_inet; The port of the corresponding server and the IP sin.sin_port of the server = Htons (13574); Sin.sin_addr. S_un. S_ADDR = inet_addr ("127.0.0.1"); if (:: Connect (S, (sockaddr*) &sin,sizeof (sin)) <0) {cout<<red<< "Can ' t connect to the server!" <<endl; System ("pause"); return 0; } cout<<green<< "Connect to the server successfully!" <<endl; while (true) {cout<<white<< "Please input your name:"; Gets (Name); if (strlen (Name) >20) cout<<red<< "Your Name should being less than characters." <<endl; else break; } SystEM ("CLS"); cout<<red<< "---===welcome===---" <<WHITE<<endl; Thread T (getmessege); T.detach (); while (true) {Sleep (+), while (! Status) if (Key_down) status^=1; Char msg[100000],sendmsg[1100]= ""; strcat (Sendmsg,name); strcat (Sendmsg, "("); strcat (SENDMSG,MYIP); strcat (sendmsg, ")"); strcat (sendmsg, "="); Setbuf (Stdin,null); while (true) {cout<<white<< "Input:"; Gets (MSG); if (strlen (MSG) >1000) cout<<red<< "Your message should is less than" characters. " <<endl; else break; } strcat (SENDMSG,MSG); :: Send (S,sendmsg,strlen (sendmsg), 0); Status^=1; } closesocket (s); WSACleanup (); return 0;}
Here is a header file (TextColor.h) that sets the color of the output content
#pragma once#include <iostream> #include <windows.h>inline std::ostream& BLUE (Std::ostream &s) { HANDLE hstdout = GetStdHandle (Std_output_handle); Setconsoletextattribute (hStdOut, foreground_blue| foreground_green| foreground_intensity); return s;} Inline std::ostream& RED (std::ostream &s) {HANDLE hstdout = GetStdHandle (Std_output_handle); Setconsoletextattribute (hstdout,foreground_red| foreground_intensity); return s;} Inline std::ostream& GREEN (std::ostream &s) {HANDLE hstdout = GetStdHandle (Std_output_handle); Setconsoletextattribute (hstdout,foreground_green| foreground_intensity); return s;} Inline std::ostream& YELLOW (std::ostream &s) {HANDLE hstdout = GetStdHandle (Std_output_handle); Setconsoletextattribute (hstdout,foreground_green| foreground_red| foreground_intensity); return s;} Inline std::ostream& White (std::ostream &s) {HANDLE hstdout = GetStdHandle (Std_output_handle); SetconsoletextattriBute (hstdout,foreground_red| foreground_green| Foreground_blue); return s;} struct color{color (WORD attribute): M_color (attribute) {}; WORD M_color;}; Template <class _elem, class _traits>std::basic_ostream<_elem,_traits>& operator<< (std::basic _ostream<_elem,_traits>& I, color& c) {HANDLE hstdout=getstdhandle (std_output_handle); Setconsoletextattribute (Hstdout,c.m_color); return i;}
The above is the complete code, here again to mention the whole project encountered problems.
The biggest problem is the input message, the first is an infinite loop read, and later found: if the input process received a message from the server, printed out will be after the input, the format is chaotic. Later think of a few ways to solve, one can be in the user press ENTER after the message received before printing out, two can be set a special button, press can enter the suspended state, and then the user input information (this process will not accept the message), after the user presses ENTER after the send, Prints the message that was received in this procedure. After careful consideration, think the second method is better, and then use the ESC key as the input key.
Finally, summarize the bug that this program still exists:
1. When the user enters their own name or message, I read it with get (I don't have to say, get the loophole everyone knows it). The loophole doesn't want to change ( I'm not going to tell you that I'm lazy ).
2. When the user is not in the input state, if casually press the keyboard, and then press a carriage return, [ESC] into the input state will be the random message sent out. (This thing I learned shallow, even if the input buffer is emptied out, if the reader has any better solution, please write in the comments, Bo Lord grateful!!!!! (? _ ?) )
After all, I'm just a tall konjac konjac ... The program does not write well, at least it is an introductory tutorial bar ...
[Multithreaded Communication program] A multi-person online communication program based on socket for C + +