⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ztcp.c

📁 十七种模拟器源代码 非常有用的作课程设计不可缺少的
💻 C
📖 第 1 页 / 共 3 页
字号:
//Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later
//version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


/**********************************************************\
* ZSNES TCP/IP MODULE FOR NETWORK PLAY                     *
*                                                          *
* Coded by the ZSNES team                                  *
*   TCP/IP drivers coded by _Demo_, revised by Pharos      *
*   UDP drivers coded by _Demo_, revised by zsKnight       *
*   Gameplay netplay implementation by zsKnight            *
*   UDP Packet loss/out of order algorithm/implementation  *
*     by zsKnight, assistance on normal packets by Pharos  *
\**********************************************************/

// UDP Algorithm:
//
// UDP Header (1 byte): 1 = Normal Packet w/ reply req, 2 = Reply Packet,
//            3 = Gameplay Packet (single byte),
//            4 = Gameplay Packet (larger packet), 5 = Re-request gameplay
//            packet
//
// Normal Packets:
//   Note: The actual implementation turned out to be quite different
//         than the below descriptions.
//   First byte contains the packet counter, followed by packet contents.
//   Remote will send a Reply Packet (just contains packet counter)
//   Each packet buffer will have a timer counter which decreases after
//     every 1/60 seconds (value set at start is 60).  If this reaches 0
//     that packet will be re-sent and reset the timer value back to 60.
//   If the local side receives the reply packet, it will set the timer
//     counter to -1.
//   
// Gameplay Packets:
//   Note: Gameplay counter is separate from normal packet counter.
//   Note2: When referring to TCP/IP, it refers to the Normal Packets above.
//   Each packet in TCP/IP will contain a byte counter when UDP is
//     enabled.
//   Each UDP packet will contain a byte counter, the number of packets,
//     then each packet will contain a byte size only if there are > 1
//     packets.  If the packet is just one byte long and contains a value<2,
//     it will follow by a byte containing info on how many packets its has
//     been like that for (it will not go beyond 32).  If the packet is
//     more than one byte long, it will repeat that packet as the extra
//     packets for the next 3 packets, with the first byte of those packets
//     as the byte counter of that packet, then the second as the size.
//     Also, the send data will be stored in a 256*32 byte buffer in case
//     of packet loss.
//   When receiving, since no UDP packets will exceed 32bytes in length,
//     there will be a 256*32 byte buffer and a 256 byte flag buffer.
//     The flag clearing pointer will move at an offset of 128 from the
//     actual point of the receive buffer.  When it receives data from
//     the UDP (or TCP), if the byte count of the data matches the
//     receive pointer, it will just send the data directly and increase the
//     receive pointer.  Else it will fill the buffer accordingly based on
//     the send data (for a maximum of 32 bytes).  Then if the bit on the
//     flag buffer is set for the current receive pointer, return the
//     appropriate buffer and increase receive pointer.
//   In case of packet loss, if no data has been received for every 500ms, the
//     local side would send a re-send package request.  What this would
//     do is let the remote side build up a package containing all the
//     data from the requested send point to the current receive point.
//     A resend request will start off with 0x00,0xFF, then the counter
//     number.  A resent packet will start off with 0x00,0xFE, the # of
//     packets, then the packet data (size of packet, data).  A resend will
//     only be done if the requested packet is within the past 64 packets.
//   In-game chat will be moved to a separate packet in TCP/IP

#include <stdio.h>
#include <string.h>
#include <time.h>
#ifdef __LINUX__
#include <sys/time.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/ioctl.h>
#ifndef __FreeBSD__
#include <asm/ioctls.h> // for FIONREAD
#else
#include <sys/filio.h> // for FIONREAD
#endif
#else
#include <windows.h>
#include <winsock.h>
#endif

#ifdef __LINUX__
#define closesocket(A) close(A)
#define CopyMemory(A,B,C) memcpy(A,B,C)
#define STUB_FUNCTION fprintf(stderr,"STUB: %s at " __FILE__ ", line %d, thread %d\n",__FUNCTION__,__LINE__,getpid())
#define UINT unsigned int
#define WORD unsigned short
#define SOCKET int
#define SOCKADDR_IN struct sockaddr_in
#define LPSOCKADDR struct sockaddr*
#define LPHOSTENT struct hostent*
#define HOSTENT struct hostent
#define LPINADDR struct in_addr*
#define LPIN_ADDR struct in_addr*
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
#endif

int RecvPtr;
int RecvPtr2;
unsigned char RecvFlags[256];
unsigned char RecvBuffer[256*32];
int RecvBufferSize[256];

int SendPtr;
int SendPtr2;
unsigned char SendBuffer[256*32];
int SendBufferSize[256];

int SendRepeated;

int PrevSPacket[16];
int PrevSData[16*32];
int PrevSSize[16];
int PrevSPtr[16];

int tcperr;
unsigned short portval;
int UDPEnable = 1;
int UDPConfig = 1;
int UDPBackTrace = 6;
int blahblahblah = 0;
int CounterA = -1;
int CounterB = -1;
int UDPMode2 = 0;

int packetnum,packetnumhead;
int packetrecvhead;
unsigned char packetdata[2048*16];
unsigned char packetrdata[2048*32];
int packetconfirm[256];
int packetreceived[256];
int packetreceivesize[256];
int packetsize[256];
unsigned char cpacketdata[2048+32];
UINT ConnectAddr;
int packettimeleft[256];
int packetresent[256];
int PacketCounter=0;
unsigned char CLatencyVal=0;


SOCKET   gamesocket;    /* tcp socket for the game */
SOCKET   serversocket;  /* tcp socket when the server is listening */

SOCKET   ugamesocket;    /* udp socket sending */
SOCKET   userversocket;  /* udp socket listening */

SOCKADDR_IN    serveraddress; /* address of the server */
SOCKADDR_IN    ugameaddress; /* address of the server */
SOCKADDR_IN    userveraddress; /* address of the server */

char blah[256];
char remotehost[256];
char hostname[50] = "IP N/A";

// Function Prototypes

int SendData(int dsize,unsigned char *dptr);
int GetData(int dsize,unsigned char *dptr);

/**********************************************************\
* Initialize the zsnes tcpip module                        *
* - no parameters                                          *
* - return 0 on success other value on error               *
*                                                          *
* - no known side effects                                  *
\**********************************************************/

int InitTCP()
{

#ifndef __LINUX__
   char blah[255];
   WORD versionneeded = MAKEWORD(2,2);
   WSADATA wsadata;
#endif

   UDPEnable=0;

#ifndef __LINUX__
   /* Startup winsock */
   WSAStartup(versionneeded, &wsadata);

   /* Verify version number and exit on wrong version */
   if (wsadata.wVersion != versionneeded)
	{	
      return(-1);
	}
	serversocket=INVALID_SOCKET;
#endif
   return(0);
}


/**********************************************************\
* Deinitialize the zsnes tcpip module                      *
* - no parameters                                          *
*                                                          *
* - no known side effects                                  *
\**********************************************************/

void DeInitTCP()
{
#ifndef __LINUX__
	WSACleanup();
#endif
}

/**********************************************************\
* Gets UDP Status through sending data                     *
* - no parameters                                          *
*                                                          *
* - no known side effects                                  *
\**********************************************************/

void GetUDPStatus() {
  int retval;

  UDPEnable=UDPConfig;

  if (!UDPEnable){
    blah[0]=0;
    retval = send(gamesocket,blah,1,0);
    gethostname(blah,255);
    retval = send(gamesocket,blah,strlen(blah),0);
  }
  else {
    blah[0]=1;
    retval = send(gamesocket,blah,1,0);
    gethostname(blah,255);
    retval = send(gamesocket,blah,strlen(&blah[1])+1,0);
  }

  retval = recv(gamesocket,blah,256,0);
  if (blah[0]==0) UDPEnable=0;
  retval = recv(gamesocket,blah,256,0);
}

/**********************************************************\
* Connect to game server                                   *
* - parameters                                             *
*     - pointer server name                                *
*     - server port                                        *
* - return 0 on success other value on error               *
*                                                          *
* - no known side effects                                  *
\**********************************************************/

int isipval(char *name){
  int i;
  i=0;
  while(name[i]!=0){
    if (!((name[i]=='.') || ((name[i]>='0') && (name[i]<='9'))))
      return(0);
    i++;
  }
  return(1);
}

int ConnectServer(char *servername, unsigned int port)
{
   char blah[255];
   int retval,i;
   LPHOSTENT host1=NULL;
   int yesip;
#ifndef __LINUX__
   WSADATA wsadata;
#endif

   packetnum = 0;
   packetnumhead = 0;
   packetrecvhead = 0;
   RecvPtr = 0;
   SendPtr = 0;
   RecvPtr2 = 0;
   SendPtr2 = 0;

   ConnectAddr = 0;
   SendRepeated = 0;
   for (i=0;i<16;i++)
     PrevSPacket[i]=0;

   /* get host and verify if it is valid */
   yesip = isipval(servername);
   if (!yesip){
     host1 = gethostbyname(servername);
     if (host1 == NULL)
     {
        return(-1);
     }
   }

//   return(-1);
   if (UDPConfig) UDPEnable = 1;

   if (UDPEnable)
   {
      PacketCounter=1;
      for (i=0;i<256;i++) {packettimeleft[i]=-1; packetconfirm[i]=1; packetreceived[i]=0; RecvFlags[i]=0;}

      userveraddress.sin_family = AF_INET;
      ugameaddress.sin_family = AF_INET;

      if (!yesip)
      {
         ugameaddress.sin_addr = *( (LPIN_ADDR) *host1->h_addr_list );
      }
      else
      {
         ugameaddress.sin_addr.s_addr = inet_addr(servername);
      }

      ConnectAddr = ugameaddress.sin_addr.s_addr;

      userveraddress.sin_addr.s_addr = INADDR_ANY;

//      port++;
      ugameaddress.sin_port = htons((unsigned short) port);
      userveraddress.sin_port = htons((unsigned short) port);
//      port--;

      userversocket = socket(AF_INET, SOCK_DGRAM,0);
      ugamesocket = socket(AF_INET, SOCK_DGRAM,0);

      if (ugamesocket == INVALID_SOCKET)
      {
#ifdef __LINUX__
	      STUB_FUNCTION;
#else
                 tcperr=WSAGetLastError();
                 sprintf(blah,"Could not initialize UDP(2) : %d",tcperr);
                 MessageBox(NULL,blah,"Error",MB_SYSTEMMODAL|MB_OK);
#endif
                 return(-2);
      }

      if (userversocket == INVALID_SOCKET)
      {
#ifdef __LINUX__
	      STUB_FUNCTION;
#else
                 tcperr=WSAGetLastError();
                 sprintf(blah,"Could not initialize UDP(2.5) : %d",tcperr);
                 MessageBox(NULL,blah,"Error",MB_SYSTEMMODAL|MB_OK);
#endif
		 return(-2);
      }

      if (bind(userversocket,(struct sockaddr*)&userveraddress,sizeof(userveraddress))==
          SOCKET_ERROR)
      {
#ifdef __LINUX__
	      STUB_FUNCTION;
#else
         tcperr=WSAGetLastError();
         sprintf(blah,"Could not initialize UDP(16) : %d",tcperr);
         MessageBox(NULL,blah,"Error",MB_SYSTEMMODAL|MB_OK);
#endif
         return(-2);
      }


//      blah[0]=1;
//      retval = sendto(ugamesocket,blah,1,0,(struct sockaddr*)&ugameaddress,sizeof(struct sockaddr));
//      if (retval == SOCKET_ERROR) return(-1);

      blah[0]=1;
      SendData(1,blah);

//      retval = sendto(ugamesocket,blah,5,0,(struct sockaddr*)&ugameaddress,sizeof(struct sockaddr));
//      blah[0]=0;
//      i = sizeof(struct sockaddr);
//      retval = recvfrom(userversocket,blah,5,0,(struct sockaddr*)&userveraddress,&i);

//      MessageBox(NULL,blah,
//              "Error",
//              MB_SYSTEMMODAL|MB_OK);
      
      return(0);

//      retval = send(gamesocket,blah,1,0);
//      retval = recv(gamesocket,blah,1,0);
   }


   /* create the game socket and verify if it is valid */
   gamesocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (gamesocket == INVALID_SOCKET)
	{
      return(-2);
	}


   /* initialize server address */
   serveraddress.sin_family = AF_INET;
   if (!yesip)
     serveraddress.sin_addr = *( (LPIN_ADDR) *host1->h_addr_list );
   else
     serveraddress.sin_addr.s_addr = inet_addr(servername);

   serveraddress.sin_port = htons((unsigned short)port);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -