📄 atalk.c
字号:
// Module Name: Atalk.c
//
// Description:
// This sample illustrates how to use the AppleTalk PAP and ADSP
// protocol. This sample either acts as a sender or receiver.
// If acting as the receiver use the -z -t and -n options to
// specify the zone, type, and object name of your receiver
// (server). If acting as the sender specify the -s options
// and the -z -t and -n options refer to the name of the
// AppleTalk endpoint to connect to (i.e. the receiver).
//
// Compile:
// cl -o Atalk Atalk.c wsock32.lib
//
// Command line parameters/options:
// usage: atalk [-s] [-z:Zone] [-t:Type] [n:Object] [-c:x] [-b:x] [-p:str]
// -s Act as a sender
// -z:Zone AppleTalk zone
// -t:Type AppleTalk type name
// -n:Object AppleTalk object name
// -c:x Number of packets to send
// -b:x Buffer size to send
// -p:str Specifies protocol (PAP or ADSP)
//
#include <windows.h>
#include <winsock.h>
#include <atalkwsh.h>
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_ZONE "*"
#define DEFAULT_TYPE "Windows Sockets"
#define DEFAULT_OBJECT "Appletalk-App"
// The maximum size of a PAP message is 4096 bytes
//
#define MAX_BUFFER 4096
#define DEFAULT_COUNT 20
#define MAX_PROTO 32
BOOL bSender=FALSE;
char szZone[MAX_ENTITY], // Zone to lookup
szType[MAX_ENTITY], // Type the object belongs to
szObject[MAX_ENTITY]; // Appletalk object (name) to
DWORD dwSendSize=MAX_BUFFER, // Number of bytes to send
dwCount=DEFAULT_COUNT; // Number of packets to send
int iProto=ATPROTO_PAP, // Protocol to use (PAP or ADSP)
iSocketType=SOCK_RDM; // Socket type of the given protocol
// PAP == SOCK_RDM while
// ADSP == SOCK_STREAM
//
// Function: usage
//
// Description:
// Print usage information and exit.
//
void usage()
{
printf("usage: pap [-s] [-z:Zone] [-t:Type]"
" [n:Object] [-c:x] [-b:x]\n");
printf(" -s Act as a sender\n");
printf(" -z:Zone AppleTalk zone\n");
printf(" -t:Type AppleTalk type name\n");
printf(" -n:Object AppleTalk object name\n");
printf(" -c:x Number of packets to send\n");
printf(" -b:x Buffer size to send\n");
printf(" -p:[adsp|pap] Protocol to use\n");
ExitProcess(1);
}
//
// Function: ValidateArgs
//
// Description:
// This function parses the command line arguments and sets
// several global variables based upon the supplied commands.
//
void ValidateArgs(int argc, char **argv)
{
char szProtoBuff[MAX_PROTO];
int i;
for(i = 1; i < argc; i++)
{
if ((argv[i][0] == '-') || (argv[i][0] == '/'))
{
switch (tolower(argv[i][1]))
{
case 's': // act as a sender
bSender = TRUE;
break;
case 'z': // zone name
strcpy(szZone, &argv[i][3]);
break;
case 't': // type name
strcpy(szType, &argv[i][3]);
break;
case 'n': // object name
strcpy(szObject, &argv[i][3]);
break;
case 'c': // number of packets to send
dwCount = atoi(&argv[i][3]);
break;
case 'b': // size of packet to send
dwSendSize = atoi(&argv[i][3]);
if (dwSendSize > MAX_BUFFER)
usage();
break;
case 'p': // protocol to use
if (strlen(argv[i]) > 3)
{
if (!stricmp(&argv[i][3], "adsp"))
{
iProto = ATPROTO_ADSP;
iSocketType = SOCK_STREAM;
}
else if (!stricmp(&argv[i][3], "pap"))
{
iProto = ATPROTO_PAP;
iSocketType = SOCK_RDM;
}
}
break;
default:
usage();
break;
}
}
}
return;
}
//
// Function: RegisterName
//
// Description:
// Register an AppleTalk name on the network
//
int RegisterName(SOCKET s, char *zone, char *type, char *obj)
{
WSH_NBP_NAME nbpname;
int ret;
// Fill out the WSH_NBP_NAME structure
//
ZeroMemory(&nbpname, sizeof(nbpname));
lstrcpy(nbpname.ZoneName, zone);
nbpname.ZoneNameLen = strlen(zone);
lstrcpy(nbpname.TypeName, type);
nbpname.TypeNameLen = strlen(type);
lstrcpy(nbpname.ObjectName, obj);
nbpname.ObjectNameLen = strlen(obj);
printf("Registering: %s:%s@%s\n", obj, type, zone);
ret = setsockopt(s, SOL_APPLETALK, SO_REGISTER_NAME,
(char *)&nbpname, sizeof(nbpname));
if (ret == SOCKET_ERROR)
{
printf("setsockopt(SO_REGISTER_NAME) failed: %d\n",
WSAGetLastError());
return 1;
}
return 0;
}
//
// Function: FindName
//
// Description:
// Lookup a given name on the AppleTalk network so that we can
// get the network, node, and socket number associated with it
// in order to make a connection.
//
int FindName(SOCKET s, char *zone, char *type, char *obj,
SOCKADDR_AT *addr)
{
char szLookup[MAX_BUFFER],
*lpLookup;
PWSH_LOOKUP_NAME lpLookupName=NULL;
int size = MAX_BUFFER,
ret;
PWSH_NBP_TUPLE lpTuple;
lpLookupName = (PWSH_LOOKUP_NAME)szLookup;
//
// Fill in our WSH_LOOKUP_NAME structure with the name to find
//
strcpy(lpLookupName->LookupTuple.NbpName.ObjectName, obj);
lpLookupName->LookupTuple.NbpName.ObjectNameLen = strlen(obj);
strcpy(lpLookupName->LookupTuple.NbpName.TypeName, type);
lpLookupName->LookupTuple.NbpName.TypeNameLen = strlen(type);
strcpy(lpLookupName->LookupTuple.NbpName.ZoneName, zone);
lpLookupName->LookupTuple.NbpName.ZoneNameLen = strlen(zone);
ret = getsockopt(s, SOL_APPLETALK, SO_LOOKUP_NAME,
(char *)szLookup, &size);
if (ret == SOCKET_ERROR)
{
printf("getsockopt() failed; %d\n", WSAGetLastError());
return 1;
}
lpLookup = (char *)szLookup + sizeof(WSH_LOOKUP_NAME);
lpTuple = (PWSH_NBP_TUPLE)lpLookup;
//
// Note that we only return the first name returned
//
addr->sat_family = AF_APPLETALK;
addr->sat_net = lpTuple[0].Address.Network;
addr->sat_node = lpTuple[0].Address.Node;
addr->sat_socket = lpTuple[0].Address.Socket;
return 0;
}
//
// Function: atalkrecv
//
// Description:
// On a socket read as much data as there is pending. For the PAP
// protocol this means reading until WSARecvEx() returns without
// the MSG_PARTIAL flag set. For ADSP we simply request to read
// the maximum buffer size. If an error occurs we return the
// Winsock error; otherwise a zero is returned. For ADSP we are
// assuming that the message from can be read on the first
// attempt.
//
int atalkrecv(SOCKET s, char *recvbuff, int *nRead)
{
int iFlags=0,
ret;
DWORD dwErr;
BOOL bDone=FALSE;
struct fd_set fdread;
*nRead = 0;
dwErr = 0;
if (iProto == ATPROTO_PAP)
{
// For PAP we have to do a prime read first
//
ret = setsockopt(s, SOL_APPLETALK, SO_PAP_PRIME_READ,
recvbuff, MAX_BUFFER);
if (ret == SOCKET_ERROR)
{
printf("setsockopt() failed: %d\n",
(dwErr = WSAGetLastError()));
return dwErr;
}
}
FD_ZERO(&fdread);
FD_SET(s, &fdread);
select(0, &fdread, NULL, NULL, NULL);
while (!bDone)
{
// Make sure we receive the whole message (PAP only)
// For the ADSP protocol, WSARecvEx() will never
// return the MSG_PARTIAL flag
//
if ((ret = WSARecvEx(s, &recvbuff[(*nRead)],
MAX_BUFFER, &iFlags)) == SOCKET_ERROR)
{
if ((dwErr = WSAGetLastError()) == WSAEWOULDBLOCK)
break;
else if (dwErr == WSAENOTCONN)
break;
printf("WSARecvEx() failed: %d\n", dwErr);
return dwErr;
}
if (ret == 0)
{
printf("graceful close\n");
break;
}
if ((iFlags & MSG_PARTIAL) == 0)
bDone = TRUE;
(*nRead) += ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -