Linux 网络编程实例

  1 /*socket->bind->listen->accept->recv/recvfrom->send/sendto->close

  2 

  3   客户端:socket->connect->send/sendto->recv/recvfrom->close

  4 

  5   其中服务器端首先建立起socket,然后调用本地端口的绑定,接着就开始与客服端建立联系,并接收客户端发送的消息。

  6   客户端则在建立socket之后调用connect函数来建立连接。

  7 

  8   服务器端的源代码如下所示:*/

  9 

 10 /*"server.c"*/

 11 

 12 #include<sys/types.h>

 13 #include<sys/socket.h>

 14 #include<stdio.h>

 15 #include<stdlib.h>

 16 #include<errno.h>

 17 #include<string.h>

 18 #include<unistd.h>

 19 #include<netinet/in.h>

 20 

 21 #define PORT  3490    //端口

 22 

 23 #define BUFFER_SIZE  1024        //缓冲区大小

 24 

 25 #define MAX_QUE_CONN_NM  5    //服务器等待连接队列的最大长度。

 26 

 27 int main(){

 28 

 29     struct sockaddr_in server_sockaddr,client_sockaddr;     //分别定义服务器和客户端套接字

 30     int sin_size,recvbytes;

 31     int server_fd,client_fd;

 32     char buf[BUFFER_SIZE];            //缓冲区

 33 

 34     /*

 35        SOCKET PASCAL FAR socket( int af, int type, int protocol);

 36        af:一个地址描述。目前仅支持AF_INET格式,也就是说ARPA Internet地址格式。

 37        type:指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。

 38        常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。

 39        protocol:顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。

 40        常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,

 41        它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

 42      */

 43     if((server_fd = socket(AF_INET,SOCK_STREAM,0))== -1){  //建立socket连接www.linuxidc.com

 44         perror("create socket fail");

 45         exit(1);

 46     }

 47 

 48     printf("Socket id=%d\n",server_fd);

 49 

 50     /*设置sockaddr_in结构体中的相关参数*/

 51 

 52     server_sockaddr.sin_family = AF_INET;

 53     server_sockaddr.sin_port = htons(PORT);   //由于在写网络程序时字节的网络顺序和主机顺序会有问题

 54     server_sockaddr.sin_addr.s_addr = INADDR_ANY;    //即0.0.0.0 任意地址

 55     bzero(&(server_sockaddr.sin_zero),8);

 56     int i = 1;  //允许重复使用本地地址与套接字进行绑定

 57 

 58     /*int PASCAL FAR setsockopt(SOCKET s,int level,int optname,const char FAR *optval,int optlen);

 59       s:标识一个套接字的描述符。

 60       level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。

 61       optname:需设置的选项。

 62       optval:指针,指向存放选项值的缓冲区。

 63       optlen:optval缓冲区长度。

 64      */

 65     setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i));  

 66 

 67     /*

 68        int bind(SOCKET socket, const struct sockaddr *address,

 69        socklen_t address_len);

 70        参数说明:

 71        socket:是一个套接字。

 72        address:是一个sockaddr结构指针,该结构中包含了要结合的地址和端口号。

 73        address_len:确定address缓冲区的长度。

 74        返回值:如果函数执行成功,返回值为0,否则为SOCKET_ERROR。

 75      */

 76     if(bind(server_fd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr)) == -1){  //绑定函数bind

 77         perror("bind fail");

 78         exit(1);

 79     }

 80 

 81     printf("Bind success!\n");

 82 

 83     /*

 84        int PASCAL FAR listen( SOCKET s, int backlog);

 85        S:用于标识一个已捆绑未连接套接口的描述字。

 86        backlog:等待连接队列的最大长度。

 87      */

 88     if(listen(server_fd,MAX_QUE_CONN_NM)== -1){  //调用listen函数,创建为处理请求的队列

 89         perror("listen fail");

 90         exit(1);

 91     }

 92 

 93     printf("Listening......\n");

 94 

 95     /*

 96        SOCKET PASCAL FAR accept( SOCKET s, struct sockaddr FAR* addr,int FAR* addrlen);

 97        s:套接口描述字,该套接口在listen()后监听连接。

 98        addr:(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。

 99        addrlen:(可选)指针,输入参数,配合addr一起使用,指向存有addr地址长度的整型数。

100      */

101     if((client_fd = accept(server_fd,(struct sockaddr *)&client_sockaddr,&sin_size))==-1){//调用accept函数,等待客户端的接

102         perror("accept fail");

103         exit(1);

104     }

105 

106     printf("server: got connection from %s \n",inet_ntoa(client_sockaddr.sin_addr));

107 

108     memset(buf,0,sizeof(buf));

109     /*

110        int PASCAL FAR recv( SOCKET s, char FAR* buf, int len, int flags);

111        s:一个标识已连接套接口的描述字。

112        buf:用于接收数据的缓冲区。

113        len:缓冲区长度。

114        flags:指定调用方式。通常写成0

115      */

116     if((recvbytes = recv(client_fd,buf,BUFFER_SIZE,0)) == -1){//调用recv函数接收客户端的请求

117         perror("recv fail");

118         exit(1);

119     }

120     

121     printf("Received a message: %s\n",buf);

122     

123 

124     /*向客户起写数据*/        

125     if(write(client_fd,"客户端我收到你发来的数据了,你能收到这句应答吗?\n",1024)==-1)

126         perror("write error!");        

127     

128     close(client_fd);

129 

130     close(server_fd);

131     exit(0);

132 }

133 

134 

135 

136 

137 

138 /*客户端*/

139 /*client.c  运行方式:./client localhost*/

140 #include <stdio.h>

141 #include <stdlib.h>

142 #include <errno.h>

143 #include <string.h>

144 #include <netdb.h>

145 #include <sys/types.h>

146 #include <netinet/in.h>

147 #include <sys/socket.h>

148 #define PORT 3490

149 #define MAXDATASIZE 5000

150 int main(int argc,char **argv)

151 {

152     int sockfd,nbytes;

153     char buf[1024];

154     struct hostent *he;

155     struct sockaddr_in srvaddr;

156     if(argc!=2)

157     {

158         perror("Usage:client hostname\n");

159         exit(1);

160     }

161     /*函数gethostbyname获得指定域名地址所对应的ip地址*/

162     if((he=gethostbyname(argv[1]))==NULL)

163     {

164         perror("gethostbyname");

165         exit(1);

166     }

167     /*创建套接字,返回套接字描述符*/

168     if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)

169     {

170         perror("create socket error");

171         exit(1);

172     }

173     bzero(&srvaddr,sizeof(srvaddr));

174     /*用获得的远程服务器进程的ip地址和端口号来填充一个internet套接字地址结构*/

175     srvaddr.sin_family=AF_INET;

176     srvaddr.sin_port=htons(PORT);

177     srvaddr.sin_addr=*((struct in_addr *)he->h_addr);

178     /*用connect于这个远程服务器建立一个internet连接*/

179     if(connect(sockfd,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr))==-1)

180     {

181         perror("connect error");

182         exit(1);

183     }

184     

185     

186     if((send(sockfd,"客户端向服务端发送数据,服务端你收到了吗?",1024,0)) == -1)

187     {

188         perror("send error");

189         exit(1);

190     }

191     

192 

193     

194     /*调用read函数读取服务器write过来的信息*/

195     if((nbytes=read(sockfd,buf,MAXDATASIZE))==-1)

196     {

197         perror("read error");

198         exit(1);

199     }

200     buf[nbytes]='\0';

201     printf("read: %s",buf);

202     close(sockfd);

203 }
View Code

 

运行方式: gcc -o service service.c

      gcc -o client client.c

     chmod +x service

      chmod +x client

在一个终端运行:./service

在另一个终端运行:./client localhost

服务端输出:

Socket id=3 Bind success! Listening...... server: got connection from 127.0.0.1 Received a message: 客户端向服务端发送数据,服务端你收到了吗?

 

客户端输出:

read: 客户端我收到你发来的数据了,你能收到这句应答吗?

你可能感兴趣的:(linux)