Server:
TcpServer.cpp: Defines the entry point for a console application. #include "stdafx.h" #include <winsock2. h> #include <iostream> #pragma comment (lib, "Ws2_32.lib") #define PORT 9990 #define Data_bufsize 8192//define socket information typedef struct _SOCKET_INFORMATION {CHAR buffer[data_bufsize]; Buffer wsabuf to send and receive data databuf; Defines the structure that sends and receives data buffers, including the length of the buffer and the contents of the socket socket; Socket DWORD Bytessend that communicates with the client; The number of bytes sent by the save socket DWORD bytesrecv;
Save the number of bytes received by the socket} socket_information, * lpsocket_information; DWORD totalsockets = 0; Record the total number of sockets being used lpsocket_information socketarray[fd_setsize]; Holds an array of socket information objects, Fd_setsize represents the maximum number of sockets allowed in the Select model//Create socket Information BOOL createsocketinformation (socket s) {L Psocket_information SI; Information to hold the socket/printf ("Accepted socket number%d\n",s); Open the accepted socket number//Allocate memory space for si (si = (lpsocket_information) globalalloc (gptr, sizeof (socket_info
rmation) = = = NULL) {printf ("GlobalAlloc () failed with error%d\n", GetLastError ());
return FALSE;
}//Initialize the value of SI Si->socket = s;
si->bytessend = 0;
SI->BYTESRECV = 0;
Add a new element to the Socketarray array to hold the Si object socketarray[totalsockets] = si; totalsockets++;
Increase the number of sockets (TRUE); ///Removes the specified Lpsocket_information object void freesocketinformation (DWORD Index) {Lpsocket_inf from the array socketarray Ormation SI = Socketarray[index];
Gets the Lpsocket_information object that corresponds to the specified index DWORD i;
Close socket closesocket (si->socket);
printf ("Closing socket number%d\n", si->socket);
Frees the specified Lpsocket_information object resource GlobalFree (SI); Moves the element after the index index in the array forward for (i = Index; i < totalSockets;
i++) {Socketarray[i] = socketarray[i+1]; } totalsockets--; Total number of sockets minus 1}//main function, start server int _tmain (int argc, _tchar* argv[]) {socket listensocket; Listen socket socket acceptsocket; Sockets for communication with the client sockaddr_in internetaddr; The address of the server wsadata wsadata; Used to initialize the socket environment INT Ret; The return value of the WinSock API Fd_set Writeset; Acquiring a writable set of sockets Fd_set Readset; Gets the readability of the socket set DWORD total = 0; Number of sockets in a ready state DWORD sendbytes; Number of bytes sent DWORD recvbytes; Bytes Received//initialized Winsock Environment if ((Ret = WSAStartup (0x0202,&wsadata))!= 0) {printf ("Wsastart
Up () failed with error%d\n ", Ret);
WSACleanup ();
return-1; }
//Create sockets for listening socket if (Listensocket = WSASocket (af_inet, Sock_stream, 0, NULL, 0, wsa_flag_overlapped) =
= Invalid_socket) {printf ("WSASocket () failed with error%d\n", WSAGetLastError ());
return-1;
//Set listener address and port number internetaddr.sin_family = Af_inet;
INTERNETADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any);
Internetaddr.sin_port = htons (port);
Bind listener sockets to local address and port if (Bind (Listensocket, (psockaddr) &internetaddr, sizeof (internetaddr)) = = Socket_error) {
printf ("bind () failed with error%d\n", WSAGetLastError ());
return-1; //Start listening if (Listen (Listensocket, 5)) {printf ("Listen () failed with error%d\n"
, WSAGetLastError ());
return-1;
/*//Set to non-blocking mode ULONG nonblock = 1; if (ioctlsocket (Listensocket, Fionbio, &nonblock) = Socket_error) {printf ("IoCtlsocket () failed with error%d\n ", WSAGetLastError ());
return-1; ///create the corresponding Socket_information//for the listensocket socket so that listensocket can be added to the socketarray array * * * createsocketin
Formation (listensocket);
while (TRUE) {//Prepare a set of read/write sockets for network I/O notifications Fd_zero (&readset);
Fd_zero (&writeset);
Adds a listener socket to the Readset collection Listensocket fd_set (Listensocket, &readset); Adds all sockets in the Socketarray array to the Writeset and Readset collections, and the Socketarray array holds listening sockets and all sockets that communicate with the client so that you can use the Select () Determine which socket has access data or read/write data for (DWORD i=0; i<totalsockets; i++) {lpsocket_information sock
Etinfo = Socketarray[i];
Fd_set (Socketinfo->socket, &writeset);
Fd_set (Socketinfo->socket, &readset); //Determine the socket if (total = select (0, &readset, &writeset, NULL, nulls) that are ready in the read/write socket collection) = = Socket_error
) {printf ("select () returned with error%d\n", WSAGetLastError ());
return-1; ///Process all sockets sequentially.
This server is a response server that is about to receive a string from the client and then send it back to the client. for (DWORD i=0; i<totalsockets; i++) {lpsocket_information socketinfo = socketarray[i]; Socketinfo determines the readability of the current socket for the current socket information to be processed, that is, whether there is an Access connection request or can receive data if (Fd_isset SOCKETINFO->SOC Ket, &readset)) {if (Socketinfo->socket = = listensocket)//For listening sockets, readable representations There is a new connection request {total--; A ready socket minus 1//accepts a connection request and gets the socket acceptsocket if (AcceptSocket = Accept, which communicates with the client (listens Ocket, NULL, NULL)!= Invalid_socket) {printf ("Connection succeeded.")
\ n ");
///Set socket AcceptSocket to non-blocking mode//So the server is not blocked when the WSASend () function is invoked to send data Nonblock = 1;
if (ioctlsocket (AcceptSocket, Fionbio, &nonblock) = Socket_error) {
printf ("ioctlsocket () failed with error%d\n", WSAGetLastError ());
return-1; *///Create socket information, initialize lpsocket_information structure data, add AcceptSocket to Socketarr
Ay array of if (createsocketinformation (acceptsocket) = = FALSE) return-1; } else {if (wsagetlasterr or ()!= wsaewouldblock) {printf ("accept () failed with err
Or%d\n ", WSAGetLastError ());
return-1; }
}
else//Receive data {//If the current socket is in the Readset collection, it indicates that the set
There is data that can be read on the Fd_isset (Socketinfo->socket, &readset) { total--;
Reduce a ready-state socket memset (Socketinfo->buffer, ', data_bufsize); ZeroMemory (socketinfo->databuf.buf,data_bufsize);//Initialize buffer socketinfo->databuf.buf = SocketI nfo->buffer; Initialize buffer position Socketinfo->databuf.len = data_bufsize;
Initialize buffer length//Receive data DWORD Flags = 0;
if (WSARecv (Socketinfo->socket, & (Socketinfo->databuf), 1, &recvbytes, &flags, NULL, NULL) = = Socket_error {//error encoding equals Wsaewouldblock means noThere is data, otherwise indicates an exception if (WSAGetLastError ()!= wsaewouldblock) {
printf ("WSARecv () failed with error%d\n", WSAGetLastError ()); Freesocketinformation (i);
Release socket information} continue; else//Receive data {Socketinfo->byte SRECV = recvbytes; Record the number of bytes that receive data if (recvbytes = 0)/
/If 0 bytes are received, the other side closes the connection {freesocketinformation (i);
Continue
else//If the data is received successfully, print the received data {printf (SOCKETINFO->DATABUF.BUF);
printf ("\ n");
//
}
}
}
}
} else {//If the current socket is in the Writeset collection, indicates that there is data in the socket's internal data buffer that can send the IF (Fd_isset socket Info->socket, &writeset)) {total--; Reduce a ready-state socket SOCKETINFO->DATABUF.BUF = Socketinfo->buffer + socketinfo->bytessend; Initialize buffer position Socketinfo->databuf.len = socketinfo->bytesrecv-socketinfo->bytessend;
Initialize buffer length if (Socketinfo->databuf.len > 0)///If there is data that needs to be sent, send the data {
if (WSASend (Socketinfo->socket, & (Socketinfo->databuf), 1, &sendbytes, 0, NULL, NULL) = = Socket_error) {//Error encoding equals WSAEWOULDBLOCK representation
There is no data, otherwise indicates an exception if (WSAGetLastError ()!= wsaewouldblock) {
printf ("WSASend () failed with error%d\n", WSAGetLastError ()); Freesocketinformation (i);
Release socket information} continue; else {socketinfo->bytessend = Sendbytes; Record the number of bytes to send data//If the data received from the client has been sent back to the client, set the number of bytes sent and received to 0 if (Socket Info->bytessend = = socketinfo->bytesrecv) {so
cketinfo->bytessend = 0; SOCKETINFO->BYTESRECV = 0; }}}//If Listensocke
T is not ready and the error returned is not Wsaewouldblock (this error indicates a connection request that is not received), an exception}//paused, press any key to exit system ("pause");
return 0;
} Client:
TcpClient.cpp: Defines the entry point for a console application. #include "stdafx.h" #include <Winsock2.H> #include <string> #include <iostream> #pragma comment (Lib, "Ws2_32.lib") #define BUF_SIZE 64//buffer size int _tmain (int argc, _tchar* argv[]) {wsadata W Sd Used to initialize the Windows socket socket shost; Socket sockaddr_in SERVADDR for communication with the server; Server address char buf[buf_size]; Used to accept data buffer int retVal; Invokes the return value of various socket functions//Initializes Windows socket if (WSAStartup (Makeword (2,2), &WSD)!= 0) {printf
("WSAStartup failed!\n");
return 1;
///Create Socket Shost = socket (AF_INET,SOCK_STREAM,IPPROTO_IP);
if (Invalid_socket = = shost) {printf ("SOCKET failed!\n");
WSACleanup ();
return-1;
//Set server address servaddr.sin_family = af_inet; ServaDdr.sin_addr. S_un. S_ADDR = inet_addr ("127.0.0.1"); The user needs to modify Servaddr.sin_port = Htons (9990) According to the actual situation; In practical applications, it is recommended that the IP address and port number of the server be saved in the configuration file as int sserveraddlen = sizeof (SERVADDR);
Compute the length of the address//loop wait while (true) {//Connect server sleep (200);
RetVal = Connect (Shost, (LPSOCKADDR) &servaddr,sizeof (SERVADDR));
Sleep (200);
if (Socket_error = = retVal) {int err = WSAGetLastError ();
if (err = = Wsaewouldblock | | err = = wsaeinval)//cannot immediately complete operation on non-blocking socket {//sleep (500);
Continue
else if (err = = Wsaeisconn)//established connection {
Break
else {continue; printf ("Connect failed!")\ n ");
Closesocket (Shost);
WSACleanup ();
return-1;
Send a string to the server and display feedback. Sending quit will cause the server program to exit while the client program itself will exit while (true) {//Send data to the server printf ("Please input a string to Sen
D: ");
Receives the input data std::string str;
Std::getline (std::cin, str);
Copy the data entered by the user into the BUF zeromemory (buf,buf_size);
ZeroMemory (buf,buf_size);
strcpy (Buf,str.c_str ());
Loop wait while (true) {//Send data to server RetVal = Send (Shost,buf,strlen (BUF), 0);
if (Socket_error = = retVal) {int err = WSAGetLastError ();
if (err = = Wsaewouldblock)//cannot immediately complete the operation on a non-blocking socket {continue;
else {printf ("Send failed!\n"); Closesocket (Shost);
WSACleanup ();
return-1;
}} break; } while (true) {ZeroMemory (buf,buf_size); Empties the buffer that receives the data RetVal = recv (shost,buf,sizeof (BUF) +1,0); Data returned by the receiving server if (Socket_error = = retVal) {int err = WSAGetLastError ();
Get error code if (err = = Wsaewouldblock)//Receive data buffer temporarily no data {
Sleep (100);
printf ("Waiting Back msg!\n");
Continue else if (err = = Wsaetimedout | | err = = wsaenetdown) {printf ("recv FA
iled!\n ");
Closesocket (Shost);
WSACleanup ();
return-1;
} break;
} Break }//zeromemory (Buf,buf_size); Empties the buffer that receives the data//retval = recv (shost,buf,sizeof (BUF) +1,0);
Data printf from the receiving server ("Recv from server:%s\n", buf);
If quit is received, exit if (strcmp (buf, "quit") = = 0) {printf ("quit!\n");
Break
}//Release resource closesocket (Shost);
WSACleanup ();
Pause, press any key to continue system ("pause");
return 0;
}