Establish a simplest Socket class - online programming initial

xiaoxiao2021-03-06  40

Establish a simplest Socket class - online programming initial

FANCY January 4, 2005 is probably one of the most patronics of programmers. I looked at the very famous "TCP / IP Protocol Detail" in boring proceedings. So try to encapsulate an extremely simple Socket class, debugging by coding, the surprise finds that it can realize some simple transmission. Personal is pleased to release it, I hope I can help you like me and struggle to help you all the colleagues in the night. Socket is a way using UNIX file descriptors and other programs. We use the system to call Socket (). It returns a set of interface descriptors, we can call Send () and RECV () through this socket descriptor. There are two types of Internet sockets. One is "stream socket", flow socket; the other is "DataGram Socket", data sets, also called no connection interface. Flow socket is a reliable bidirectional data stream, which is uncommonly passing data, has its own error control. High quality data transmission of stream socket is implemented by the TCP protocol. File transmission like QQ, POPO is to use this method. Data setup interface It is unreliable. When you send a datagram, it may arrive, and maybe data will reverse. It uses the "UDP" protocol.

Learn about these, now let us see a real program:

//server.cpp #include #include #include #include #include #include #Include #include #define myport 6140 #define buffsize 100

Main () {int Sockfd; struct sockaddr_in my_addr; struct sockaddr_in their_addr; char buf [buffsize];

IF ((SOCKFD = Socket (AF_INET, SOCK_DGRAM, 0) == - 1) {Printf ("Socket Error / N"); exit (1);}

MY_ADDR.SIN_FAMILY = AF_INET; my_addr.sin_port = htons (myport); my_addr.sin_addr.s_addr = INADDR_ADDR_Addr = INADDR_Addr; Bzero (& (My_ADDR.SIN_ZERO), 8);

IF (Bind (STRUCKFD, STRUCKADDR *) & my_addr, sizeof (struct sockaddr)) == - 1) {Printf ("Bind Error"); exit (1);}

int addr_len = sizeof (struct sockaddr); int numbytes; if ((numbytes = recvfrom (sockfd, buf, BUFSIZE, 0, (struct sockaddr *) & their_addr, & add_len)) == - 1) {printf ( "recvfrom error") EXIT (1);

Printf ("Get Package FROM% S / N", INET_NTOA (THEIR_ADDR.SIN_ADDR); Printf ("Package IS% D Bytes / N", NumBytes); BUF [NumBytes] = '/ 0'; Printf ("Package IS / "% s /" / n ", buf); Close (SockFD);} // client.cpp #include #include #include #include #include #include #include #include #include #define myport 6140

INT Main (int Argc, char * argv []) {Int Sockfd; struct sockaddr_in their_addr; struct hostent * heiff (argc <3) {printf ("les argument / n"); exit (1);

IF ((He = gethostByname) == null) {Printf ("gethostByName Error / N); exit (1);} if ((sockfd = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {Printf ("socket error / n"); exit (1);}

THEIR_ADDR.SIN_FAMILY = AF_INET; THEIR_ADDR.SIN_PORT = HTONS (MyPort); their_addr.sin_addr = * (Struct In_Addr *) HE-> h_addr); Bzero (& (THEIR_ADDR.SIN_ZERO), 8);

Int NumBytes; IF ((NumBytes = Sendto (Sockfd, Argv [2], Strlen (Argv [2], 0, (Struct SockAddr *) & their_addr, sizeof (Struct SockAddr))) == - 1) {Printf ("Sentto Error / N "); exit (1);}

Printf ("Send% D Bytes TO% S / N", NumBytes, INET_NTOA (THEIR_ADDR.SIN_ADDR); Close (SOCKFD); Return 0;

}

From the above two programs, we can see that the steps of sending and receiving data through socket are basically as follows: First use the socket () to establish a socket, then use bind () to determine the address and port. Then you can sendTO () or Recvfrom () data. This is the general process of the data settlement interface. The flow socket is slightly different, which requires listen () to listen in the specified port. The client first is to connect to the port that is listening through connect (). Each connection will be added to the queue waiting for acceptance (ACCEPT ()). The server call accept () tells the other party's free connection. Accept () returns a new socket file descriptor. The original file descriptor continues to listen to the specified port, and the new descriptor is used to send (Send ()) and accept (RECV ()) data.

After clearing the working principle of the socket, the basic purpose is to shield some cumbersome operations, making it easier. //Esock.h#ifndef _esock_h_ # define _sock_h_

#include #include #include #include #include #include #include #include

claes ESock {private: int sin_size; int sockfd, new_fd; unsigned short port; struct sockaddr_in my_addr, their_addr, get_addr; public: ESock (); virtual ~ ESock (); int Send (const char * buf, int len); bool Connect (); int Recv (const char * buf, int len); void Accept (); void Listen (); bool Socket (int type); void setPort (unsigned short in_port); void SetRemotePort (unsigned short in_port); unsigned short getRemotePort (); bool Bind (); int Recvfrom (const char * buf, int len); int Sendto (const char * buf, int len); bool SetRemoteAddrees (const char * addrees); void GetRemoteAddrees (const char * addrees Void close ();

#ENDIF

//Esock.cpp#include "esock.h"

Esock :: esock () {}

Esock :: ~ esock () {}

Bool Esock :: Socket (INT TYPE) {IF ((Sockfd = Socket (AF_INET, TYPE, 0)) == - 1) Return False;

Return True;}

Void Esock :: setPort (unsigned short in_port) {my_addr.sin_family = Af_inet; port = in_port; my_addr.sin_port = htons (port); my_addr.sin_addr.s_addr = incdr_any;}

Void Esock :: SetRemotePort (unsigned short in_port) {THEIR_ADDR.SIN_PORT = HTONS (In_Port);

Unsigned short esock :: getRemotEport () {return ntohs (get_addr.sin_port);

Bool Esock :: Bind () {IF (bind (STRUCKD, STRUCKADDR *) & my_addr, sizeof (struct sockaddr)) == - 1) Return False;

Return True;}

int ESock :: Recvfrom (const char * buf, int len) {int numbytes; int addr_len = sizeof (struct sockaddr); if ((numbytes = recvfrom (sockfd, buf, len, 0, (struct sockaddr *) & get_addr, & addr_len )) == - 1) {RETURN FALSE;} BUF [NumBytes] = '/ 0'; return numbytes;} int est char * buf, int LEN) {Return Sendto (Sockfd, BUF, LEN, 0 (Struct SockAddr *) & their_addr, sizeof (struct sockaddr));

}

Bool Esock :: SetRemoteaddrees {struct hostent * he; if ((he = gethostbyname) == null) Return False;

THEIR_ADDR.SIN_FAMILY = AF_INET; THEIR_ADDR.SIN_PORT = HTONS (port); their_addr.sin_addr = * (Struct in_addr *) HE-> h_addr);

Return True;

}

Void Esock :: GetRemoteAddrees (const char * addrees) {structure (addrees, inet_ntoa (get_addr.sin_addr);}

Void Esock :: Close () {close (sockfd); close (new_fd);}

Void Esock :: listen () {listen (sockfd, 10);

Void Esock :: Accept () {sin_size = sizeof (struct sockaddr_in); new_fd = accept (sockfd, (struct socddr *) & gET_ADDR, & SIN_SIZE

Int Esock :: RECV (Const Char * BUF, INT LEN) {Return Recv (New_FD, BUF, LEN, 0);}

Bool Esock :: Connect () {IF (Connect (Sockfd, (Struct SockAddr *) & their_addr, sizeof (struct sockaddr)) == - 1) Return False;

Return True;}

Bint Esock :: Send (Const Char * BUF, INT LEN) {Return Send (SockFD, BUF, LEN, 0);

The above is an extremely simple SOCK package. In view of the application of the data report, it has been introduced before this, and then only posts the test code for file transfer written by this ESOCK class.

//server.cpp#include #include "esock.h" #include "efile.h"

INT main () {esock es; es.socket (Sock_Stream); es.setport (6140); es.Bind (); es.Listen (); es.accept (); char buf [1000]; MEMSET (A, '/ 0', 1000); EFILE * fd = new efile ("accept.txt", "w"); delete fd; bool flag = true; int i = 0, recvlen = 0; while (1) {recvlen = Es.Recv (BUF, 1000); if (Recvlen> 0) {EFILE * f = New Efile ("accept.txt", "a"); f-> Write (buf, sizeof (char); delete); delete f; if (flag) Printf ("geting data ... / n"); flag = false; i ; printf ("/ b / b / b / b / b"); Printf ("% 6d", I }} Return 0;

#include #include "esock.h" #include "efile.h"

INT main () {Esock ES;

Es.socket; Printf ("Input IP Address: / N"); Char IP [20]; Scanf ("% S", IP); Es.SetRemoteAddress (IP); Es.SetRemoteport (6140); ES .Connect ();

Efile File ("Send.txt", "R"); Char BUF [1000]; MEMSET (BUF, '/ 0', 1000); INT i = 0; int = 0; while (readlen = file.read BUF, SIZEOF (CHAR), 1000) {es.send (buf, readlen); i ; Printf ("/ b / b / b / b / b"); Printf ("% 6d", i); } Printf ("Send OK / N"); es.close (); return 0;}

The distant eishn transmits a approximately 2m PDF file with this program. I use FC to compare it with the original file with the original file, determine that the transmission is reliable. This is the only result that can give me a comfort. All of the above programs are compiled and run in CygWin, and the final file transfer program uses the EFILE class written by it. I believe that you should easily use the general file read and write functions. All of this is a very thick understanding and practice, please ask all the professionals to give me a childish criticism to finish!

转载请注明原文地址:https://www.9cbs.com/read-73276.html

New Post(0)