Aros/开发者/NIC驱动程序
外观
< Aros
create socket set sock addr set sock port open socket send socket ( request_string ) receive result
#include <proto/socket.h> #include <bsdsocket/socketbasetags.h>
bsdsocket.library在您启动AROSTCP后会在内存中创建。这些包括的将提供它的链接。
#include <proto/exec.h> struct Library * SocketBase = NULL; int h_errno = 0; extern int errno;
然后在初始化代码中
if(!(SocketBase = OpenLibrary("bsdsocket.library", 4 ))) { SDLNet_SetError("No TCP/IP Stack running!\n"); return(-1); } if( SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (IPTR)&errno, SBTM_SETVAL(SBTC_HERRNOLONGPTR), (IPTR)&h_errno, TAG_DONE )) { SDLNet_SetError("Error initializing bsdsocket\n"); return(-1); }
将网络应用程序的包含目录更改为$(AROS_DEVELOPMENT)/netincludes,必须将#include <bsdsocket.h>更改为include <proto/bsdsocket.h>,bsdsocket.library在libs:中不存在作为二进制文件。它是您执行“startnet”后动态创建的。
将SocketBase重新定义为一个非全局变量,例如线程特定上下文的字段。例如
#define SocketBase my_thread_context->socket_base
查看了Task结构,它有tc_UserData,正是我需要的,我可以使用它来保存每个任务的SocketBase。这种方法将起作用,即使我想在主程序中使用套接字。如果有人感兴趣,我创建了这个小头文件
#ifndef TASKSOCKBASE_H #define TASKSOCKBASE_H /* * Per-task socketbase using tc_UserData */ #include <proto/exec.h> #define SocketBase FindTask(NULL)->tc_UserData #define __BSDSOCKET_NOLIBBASE__ #include <proto/bsdsocket.h> #endif
在所有地方包含它,而不是proto/bsdsocket.h,并像往常一样使用SocketBase。
WaitSelect()的工作原理与select()相同,将这里粘贴代码部分,它失败了……sys/select.h WaitSelect只能用于套接字,不能用于DOS文件句柄。在Unix中,它们被统一处理,但在Amiga中,您必须对文件句柄和套接字使用不同的代码路径。
#ifndef select(nfds,rfds,wfds,efds,timeout) #define select(nfds,rfds,wfds,efds,timeout) WaitSelect(nfds,rfds,wfds,efds,timeout,NULL) #endif
并测试选择
struct timeval timeout; int socket_d; struct fd_set client_d; //set to 3 mins timeout.tv_sec = 3 * 60; timeout.tv_usec = 0; do { rc = select(socket_d + 1, &client_d, NULL, NULL, &timeout); /* Check to see if the select call failed. */ if (rc < 0) { perror(" select() failed"); break; } /* Check to see if the 3 minute time out expired. */ if (rc == 0) { printf(" select() timed out. End program.\n"); break; } }
socket—创建通信端点
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol)
Socket() creates an endpoint for communication and returns a descriptor. The domain parameter specifies a communications domain within which communication will take place; this selects the protocol family which should be used. These families are defined in the include file <sys/socket.h>. The currently understood formats are AF_UNIX (UNIX internal protocols), AF_INET (ARPA Internet protocols), AF_ISO (ISO protocols), AF_NS (Xerox Network Systems protocols), and AF_IMPLINK (IMP ``host at IMP link layer). AROS AMITCP/IP currently supports only AF_INET protocol family. The socket has the indicated type, which specifies the semantics of communication. Currently defined types are: SOCK_STREAM SOCK_DGRAM SOCK_RAW SOCK_SEQPACKET SOCK_RDM A SOCK_STREAM type provides sequenced, reliable, two-way connection based byte streams. An out-of-band data transmission mechanism may be supported. A SOCK_DGRAM socket supports datagrams (connectionless, unreliable messages of a fixed (typically small) maximum length). A SOCK_SEQPACKET socket may provide a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length; a consumer may be required to read an entire packet with each read system call. This facility is protocol specific, and presently implemented only for PF_NS. SOCK_RAW sockets provide access to internal network protocols and interfaces. The types SOCK_RAW, which is available only to the super-user, and SOCK_RDM, which is planned, but not yet implemented, are not described here. The protocol specifies a particular protocol to be used with the socket. Normally only a single protocol exists to support a particular socket type within a given protocol family. However, it is possible that many protocols may exist, in which case a particular protocol must be specified in this manner. The protocol number to use is particular to the "communication domain" in which communication is to take place. Sockets of type SOCK_STREAM are full-duplex byte streams, similar to pipes. A stream socket must be in a connected state before any data may be sent or received on it. A connection to another socket is created with a connect() call. Once connected, data may be transferred using recv() and send() or their variant calls. When a session has been completed a CloseSocket() may be performed. Out-of-band data may also be transmitted as described in send() and received as described in recv(). The communications protocols used to implement a SOCK_STREAM insure that data is not lost or duplicated. If a piece of data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable length of time, then the connection is considered broken and calls will indicate an error with -1 returns and with ETIMEDOUT as the specific error code (see Errno()). The protocols optionally keep sockets "warm" by forcing transmissions roughly every minute in the absence of other activity. An error is then indicated if no response can be elicited on an otherwise idle connection for a extended period (e.g. 5 minutes). SOCK_SEQPACKET sockets employ the same system calls as SOCK_STREAM sockets. The only difference is that recv() calls will return only the amount of data requested, and any remaining in the arriving packet will be discarded. SOCK_DGRAM and SOCK_RAW sockets allow sending of datagrams to correspondents named in send() calls. Datagrams are generally received with recvfrom(), which returns the next datagram with its return address. An IoctlSocket() call can be used to specify a task to receive a SIGURG signal when the out-of-band data arrives. It may also enable non-blocking I/O and asynchronous notification of I/O events via SIGIO. The operation of sockets is controlled by socket level options. These options are defined in the file <sys/socket.h>. setsockopt() and getsockopt() are used to set and get options, respectively.
A -1 is returned if an error occurs, otherwise the return value is a descriptor referencing the socket.
The socket() call fails if: [EPROTONOSUPPORT] The protocol type or the specified protocol is not supported within this domain. [EMFILE] The per-process descriptor table is full. [EACCESS] Permission to create a socket of the specified type and/or protocol is denied. [ENOBUFS] Insufficient buffer space is available. The socket cannot be created until sufficient resources are freed.
socket() calls the fdCallback() with action codes FDCB_CHECK and FDCB_ALLOC to check and mark the new descriptor as allocated if the callback is defined. See SocketBaseTagList() for more information on fdCallback().
一些示例代码教程
SocketBaseTagList—Set/Get SocketBase attributes.
#include <amitcp/socketbasetags.h> ULONG SocketBaseTagList(struct TagItem * taglist); ULONG SocketBaseTags(ULONG tag, ...);
Set or get a list of (mostly) SocketBase instance dependent attributes from the AMITCP/IP.
These functions expect as their argument a standard tag list, one or several array of struct TagItem as defined in the header file <utility/tagitem.h>. The structure contains two fields: ti_Tag and ti_Data. The ti_Tag field contains tag code, which determines what the SocketBaseTagList() should do with its argument, the ti_Data field. The include file <amitcp/socketbasetags.h> defines macros for base tag code values. Base tag code macros begin with `SBTC_' (as Socket Base Tag Code). The base tag value defines what data item the tag item refers. The tag code contains other information besides the referred data item. It controls, whether the SocketBaseTagList() should set or get the appropriate parameter, and whether the argument of the tag in question is passed by value or by reference. The include file <amitcp/socketbasetags.h> defines the following macros, which are used to construct the ti_Tag values from the base tag codes: SBTM_GETREF(code) - get by reference SBTM_GETVAL(code) - get by value SBTM_SETREF(code) - set by reference SBTM_SETVAL(code) - set by value If the actual data is stored directly into the ti_Data field, you should use the 'by value' macros, SBTM_GETVAL() or SBTM_SETVAL(). However, if the ti_Data field contains a pointer to actual data, you should use the 'by reference' macros, SBTM_GETREF() or SBTM_SETREF(). In either case the actual data should always be a LONG aligned to even address. According the used tag naming scheme a tag which has "PTR" suffix takes an pointer as its argument. Don't mix the pointer arguments with 'by reference' argument passing. It is possible to pass a pointer by reference (in which case the ti_Data is a pointer to the actual pointer). The list of all defined base tag codes is as follows: SBTC_BREAKMASK Tag data contains the INTR signal mask. If the calling task receives a signal in the INTR mask, the AMITCP/IP interrupts current function calls and returns with the error code EINTR. The INTR mask defaults to the CTRL-C signal (SIGBREAKF_C, bit 12). SBTC_DTABLESIZE Socket Descriptor Table size. This defaults to 64. SBTC_ERRNO The errno value. The values are defined in <sys-errno.h>. SBTC_ERRNOBYTEPTR SBTC_ERRNOWORDPTR SBTC_ERRNOLONGPTR SBTC_ERRNOPTR(size) Set (only) the pointer to the errno variable defined by the program. AMITCP/IP defines a value for this by default, but the application must set the pointer (and the size of the errno) with one of these tags, if it wishes to access the errno variable directly. The SBTC_ERRNOPTR(size) is a macro, which expands to one of the other (BYTE, WORD or LONG) tag codes, meaning that only 1, 2 and 4 are legal size values. The NetLib:autoinit.c sets the errno pointer for the application, if the application is linked with it. SBTC_ERRNOSTRPTR Returns an error string pointer describing the errno value given on input. You can not set the error message, only get is allowed. On call the ti_Data must contain the error code number. On return the ti_Data is assigned to the string pointer. (*ti_Data, if passed by reference). See the file <sys-errno.h> for symbolic definitions for the errno codes. SBTC_FDCALLBACK A callback function pointer for coordination of file descriptor usage between AMITCP/IP and link-library. By default no callback is called and the value of this pointer is NULL. The prototype for the callback function is: int error = fdCallback(int fd, int action); where error - 0 for success or one of the error codes in <sys-errno.h> in case of error. The AMITCP/IP API function that calls the callback usually returns the error back to the caller without any further modification. fd - file descriptor number to take action on. action - one of the action codes, which are defined in the header file <amitcp-socketbasetags.h>) as follows: FDCB_FREE - mark the fd as unused on the link library structure. If fd represents a file handled by the link library, the error ENOTSOCK should be returned. FDCB_ALLOC - mark the fd allocated as a socket. FDCB_CHECK -check if the fd is free. If an error is returned, the fd is marked as used in the AMITCP/IP structures. The AMITCP/IP calls the callback every time a socket descriptor is allocated or freed. AMITCP/IP uses the FDCB_CHECK before actual allocation to check that it agrees with the link library on the next free descriptor number. Thus the link library doesn't need to tell the AMITCP/IP if it creates a new file handle in open(), for example. See file _chkufb.c on the net.lib sources for an example implementation of the callback function for the SAS/C. SBTC_HERRNO The name resolver error code value. Get this to find out why the gethostbyname() or gethostbyaddr() failed. The values are defined in <netdb.h>. SBTC_HERRNOSTRPTR Returns host error string for error number in tag data. Host error is set on unsuccessful gethostbyname() and gethostbyaddr() calls. See the file <netdb.h> for the symbolic definitions for the herrno valus. Notes for the SBTC_ERRNOSTRPTR apply also to this tag code. SBTC_IOERRNOSTRPTR Returns an error string for standard AmigaOS I/O error number as defined in the header file <exec-errors.h>. Note that the error number taken by this tag code is positive, so the error codes must be negated (to be positive). The positive error codes depend on the particular IO device, the standard Sana-II error codes can be retrieved by the tag code SBTC_S2ERRNOSTRPTR. Notes for the SBTC_ERRNOSTRPTR apply also to this tag code. SBTC_LOGFACILITY Facility code for the syslog messages as defined in <sys/syslog.h>. Defaults to LOG_USER. SBTC_LOGMASK Sets the filter mask of the syslog messages. By default the mask is 0xff, meaning that all messages are passed to the log system. SBTC_LOGSTAT Syslog options defined in <sys/syslog.h>. SBTC_LOGTAGPTR A pointer to a string which is used by Syslog() to mark individual syslog messages. This defaults to NULL, but is set to the name of the calling program by the autoinit code in netlib:autoinit.c. This is for compatibility with pre-3.0 programs. SBTC_S2ERRNOSTRPTR Returns an error string for a Sana-II specific I/O error code as defined in the header file <devices-sana2.h>. Notes for the SBTC_ERRNOSTRPTR apply also to this tag code. SBTC_S2WERRNOSTRPTR Returns an error string for a Sana-II Wire Error code as defined in the header file <devices-sana2.h>. Notes for the SBTC_ERRNOSTRPTR apply also to this tag code. SBTC_SIGEVENTMASK Tag data contains the signal mask to be sent to the application whenever notification about socket events is in order. The default value for this is zero, inhibiting any event notifications. The application must set this mask if it desires to be notified about asynchronous socket events. When the application receives the signal specified in the mask, it can use the function GetSocketEvents() to find out what happened. SBTC_SIGIOMASK The signals specified in the mask in the tag data are sent to the calling task when asynchronous I/O is to be notified. The default value is zero, i.e., no signals are sent. The signals in the mask are sent whenever something happens on the socket. This mechanism is compatible with the Unix SIGIO signal. Since AmigaOS signals may get combined, one signal may include notification for originally distinct events on the socket. One example of this is the reception of data and connection closure. Usage of the socket events (see GetSocketEvents()) is recommended over this because of the problem described above. SBTC_SIGURGMASK The signals specified in the mask in the tag data are sent to the calling task when notification about urgent data arrives. The default value is zero, i.e. no signals are sent. This mechanism is compatible with the Unix SIGURG signal. Note that this signal does not indicate the arrival of the actual out-of-band data. If the receive buffer of the socket is full, the urgent data can't even be received. Because of this the application may need to read some normal data off the socket before it can read the urgent data.
Returns 0 on success, and a (positive) index of the failing tag on error. Note that the value 1 means first TagItem, 2 the second one, and so on. The return value is NOT a C-language index, which are 0 based.
extern LONG WaitSelect(rest);
int select(int nfds,fdset *readfds,rest) just like the header
{
return WaitSelect(rest);
}
</soruce>
==Blocking==
if your problem was O_NONBLOCK than why dont you actually use that setnonblocking()
function to enable non-blocking I/O instead of directly calling fcntl()????
also you may want to use O_NDELAY
O_NONBLOCK and O_NDELAY are same if you can use O_NDELAY
<syntaxhighlight lang="c">
int setNonblocking(int fd)
{
int flags;
/* If they have O_NONBLOCK, use the Posix way to do it */
#if defined(O_NONBLOCK)
if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
flags = 0;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else
/* Otherwise, use the old way of doing it */
flags = 1;
return ioctl(fd, FIOBIO, &flags);
#endif
}
或
IoctlSocket(socket, FIONBIO, (char *) &val);
d domain t type p protocol n name nl namelen l level r request a arg o optname ov optval ol optlen m msg l length f flags socket(d,t,p) ex. s=socket(domain, type, protocol) bind(s,n,nl) ex. success = bind(s, name, namelen) listen(s,b) accept(s,a,al) connect(s,n,nl) ex. success = connect(s, name, namelen) sendto(s,m,l,f,t,tl) send(s,m,l,f) ex. nbytes = send(s, msg, len, flags) recvfrom(s,b,l,f,fr,frl) recv(s,b,l,f) shutdown(s,h) setsockopt(s,l,o,ov,ol) getsockopt(s,l,o,ov,ol) ex. success = getsockopt(s, level, optname, optval, optlen) getsockname(s,h,n) getpeername(s,h,n) IoctlSocket(d,r,a) ex. value = IoctlSocket(fd, request, arg) CloseSocket(d) WaitSelect(n,r,w,e,t,m) SetSocketSignals(sin,sio,su) getdtablesize() ObtainSocket(i,d,t,p) ReleaseSocket(f,i) ReleaseCopyOfSocket(f,i) Errno() SetErrnoPtr(e,s) d domain t type p protocol n name nl namelen l level r request a arg o optname ov optval ol optlen m msg l length f flags Inet_NtoA(i) inet_addr(c) ex. addr = inet_addr(cp) Inet_LnaOf(i) Inet_NetOf(i) Inet_MakeAddr(n,h) inet_network(c) gethostbyname(n) gethostbyaddr(a,l,t) getnetbyname(n) getnetbyaddr(n,t) getservbyname(n,p) getservbyport(p,pr) getprotobyname(n) getprotobynumber(p) vsyslog(l,f,a) Dup2Socket(fa,fb) sendmsg(s,m,f) recvmsg(s,m,f) gethostname(h,s) gethostid() SocketBaseTagList(t) GetSocketEvents(e) getnetent(), ex. struct netent *getnetent(void); getprotoent(), ex. struct protoent *getprotoent(void); getservent(), ex. struct servent *getservent(void); the following tags are supported: SBTC_BREAKMASK SBTC_ERRNO SBTC_HERRNO SBTC_ERRNOSTRPTR SBTC_HERRNOSTRPTR SBTC_ERRNOBYTEPTR SBTC_ERRNOWORDPTR SBTC_ERRNOLONGPTR SBTC_HERRNOLONGPTR SBTC_SIGEVENTMASK
<html> <head> <title>Welcome to my site</title> <meta name="description" content=""> <meta name"keywords" content=" , ,"> </head> <frameset rows = ....> ...etc... </frameset> <noframes> <body> <h1>You need to update your browser to one that supports frames!</h1> You don't need a body at all unless you use the <noframes></noframes> tag. In all honesty you really should create a <noframes> section with nothing but navigation to the links of the rest of the page. There are still people out there who browse web sites without frames. </body> </noframes>