总的来说网络程序是由两个部分组成的--客户端和服务器端.它们的建立步骤一般是:
服务器端 socket-->bind-->listen—>accept
客户端 socket-->connect
在WINDOWS环境下使用SOCKET前需要初始化windows socket库,否则socket()会返回SOCKET_ERROR(-1)
SOCKET socket(int domain, int type,int protocol)
- domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等). AF_UNIX只能够用于单一的Unix系统进程间通信,而AF_INET是针对Internet的,因而可以允许在远程主机之间通信
- type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等) SOCK_STREAM表明我们用的是TCP协议,这样会提供按顺序的,可靠,双向,面向连接的比特流. SOCK_DGRAM 表明我们用的是UDP协议,这样只会提供定长的,不可靠,无连接的通信.
- protocol:由于我们指定了type,所以这个地方我们一般只要用0来代替就可以了 下面是from WINSOCK.H的协议定义
eg:
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
- sockfd:是由socket调用返回的文件描述符.
- addrlen:是sockaddr结构的长度.
- my_addr:是一个指向sockaddr的指针. 在WINSOCK.H中有 sockaddr的定义 :
localaddr.sin_addr.s_addr = inet_addr(ipaddr);
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(portNum);
bind(s_ , (struct sockaddr*)&localaddr , sizeof(localaddr)) ;
由于客户端不需要固定的端口号,因此不必调用bind(),客户端的端口号由内核自动分配。如果服务器不调用bind(),内核会自动给服务器分配监听端口,每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦。
int listen (SOCKET s, int backlog);
- s:bind后的SOCKET文件描述符
- backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时, 使用这个表示可以介绍的排队长度.(允许监听多少个TCP连接)
- listen函数将bind的文件描述符变为监听套接字.出错返回-1
e.g.
listen(sListen, 3);
SOCKET accept (SOCKET s, struct sockaddr *addr, int *addrlen);
- s:是listen后的SOCKET文件描述符
- addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了. bind,listen和accept是服务器端用的函数,accept调用时,服务器端的程序会一直阻塞到有一个客户程序发出了连接. accept成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了. 失败时返回-1
e.g.
sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);