和”SOCK_DGRAM”。
这两种套接字的区别在于它们使用不同的协议。流式套接字使用TCP协议,数据报套接字使用的是UDP协议。
TCP(Transmission Control Protocol)传输控制协议,是TCP/IP体系中的运输层协议,是面向连接的,因而可提供可靠的,按序传送数据流,它的可靠是因为它使用三段握手协议来传输数据,并且采用“重发机制”确保数据的正确发送,接收端收到数据后要发出一个肯定确认,而发送端必须接收到接收端的确认信息后,否则发送端会重发数据。同时TCP是无错误传递的,有自己的检错和纠错机制,使用TCP协议的套接字是属于流式套接字。大家熟知的telnet就是使用的流式套接字。
UDP(User Datagram Protocol)用户数据报协议提供无连接的不可靠的服务,在传送数据之前不需要建立连接。远地主机在接收接收到UDP数据报后,不需要给出任何应答,这样的话,如果发送一个数据报,可能到达也可能丢失。如果发送多个包,到达接收端的次序可能是颠倒的。数据报套接字有时候也称为“无连接套接字”,大家熟悉的TFTP和NFS使用的就是该协议。 大多数情况下,如果只是将数据包发送给给定地址的机器,是不能够确定到底把数据包发送给机器哪一个进程的,端口号的指定才能够更明确的指明。适用于通信的用户应用程序可以使用从1到65535的任何一个端口号,并将它分配给端口。这些号通常分成以下几个范围段:
端口0,不使用。如果传递的端口号是0,就会为进程分配一个1024到5000之间的一个没有使用的端口。
端口1~255,保留给特定的服务,如FTP,远程网,FINGER等。 端口256~1023,保留给别的一般服务如Routing function(路由函数)。 端口1024~4999,可以被任意的客户机端口所使用,客户机套接字通常会使用这个范围段的端口。
端口5000~65535,为用户定义的服务器端口所使用。如果一个客户机需要事先知道服务器的端口,那么服务器套接字就应该使用这个范围的端口值。 下面结合一个具体的服务器端的例子,使读者熟悉socket编程的方法。
/******************************************************* * Institute of Automation, Chinese Academy of Sciences * File Name: comsamp.c
* Description:communication with socket * Author: * Date:
Xueyuan Nie
*******************************************************/
#include
/*=========* * Defines * *=========*/ #ifndef TRUE #define FALSE 0
#define TRUE 1 #endif
#ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif
#ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif
#ifndef EXT_NO_ERROR #define EXT_NO_ERROR 0 #endif
#ifndef EXT_ERROR #define EXT_ERROR 1 #endif
#ifndef INVALID_SOCKET #define INVALID_SOCKET -1 #endif
#ifndef SOCK_ERR #define SOCK_ERR -1
#endif
/*==================================* * Global data local to this module *
*==================================*/ typedef int SOCKET;
typedef struct ConnectData_tag { int port; int waitForStart;
SOCKET sFd; /* socket to listen/accept on SOCKET msgFd; /* socket to send/receive messages } ConnectData;
ConnectData *CD; int i=0;
int connectionMade = 0;
/*=================* * Local functions * *=================*/ void prompt_info(int signumber) {
char src[]=\ int nBytesToSet=strlen(src);
*/ */ send(CD->msgFd, src, nBytesToSet, 0); }
void init_sigaction(void) {
struct sigaction act; act.sa_handler=prompt_info; act.sa_flags=0;
sigemptyset(&act.sa_mask); sigaction(SIGPROF,&act,NULL); }
void init_time(double t_usec) {
struct itimerval value; int int_usec;
int_usec=(int)(t_usec*1000000); value.it_value.tv_sec=0;
value.it_value.tv_usec=int_usec; value.it_interval=value.it_value; setitimer(ITIMER_PROF,&value,NULL); }
int ModeInit(void)