socket编程实践

socket编程

(1)函数说明。
socket 编程的基本函数有 socket()、 bind()、 listen()、 accept()、 send()、 sendto()、 recv()以及 recvfrom()等,其中根据客户端还是服务端,或者根据使用 TCP 协议还是 UDP 协议,这些函数的调用流程都有所区别,这里先对每个函数进行说明,再给出各种情况下使用的流程图。
socket():该函数用于建立一个 socket 连接,可指定 socket 类型等信息。在建立了 socket 连接之后,可对 sockaddr 或 sockaddr_in 结构进行初始化,以保
存所建立的 socket 地址信息。
 
bind():该函数是用于将本地 IP 地址绑定到端口号, 若绑定其他 IP 地址则不能成功。另外,它主要用于 TCP 的连接,而在 UDP 的连接中则无必要。

listen():在服务端程序成功建立套接字和与地址进行绑定之后,还需要准备在该套接字上接收新的连接请求。此时调用 listen()函数来创建一个等待队列,在其中存放未处理的客户端连接请求。

accept():服务端程序调用 listen()函数创建等待队列之后,调用 accept()函数等待并接收客户端的连接请求。它通常从由 bind()所创建的等待队列中取出第一个未处理的连接请求。

connect():该函数在 TCP 中是用于 bind()的之后的 client 端,用于与服务器端建立连接,而在 UDP 中由于没有了 bind()函数,因此用 connect()有点类似 bind()函数的作用。

send()和 recv():这两个函数分别用于发送和接收数据,可以用在 TCP 中,也可以用在 UDP 中。当用在 UDP 时,可以在 connect()函数建立连接之后再用。

sendto()和 recvfrom():这两个函数的作用与 send()和 recv()函数类似,也可以用在 TCP 和 UDP 中。 当用在 TCP 时, 后面的几个与地址有关参数不起作用,函数作用等同于 send()和 recv();当用在 UDP 时,可以用在之前没有使用connect()的情况下,这两个函数可以自动寻找指定地址并进行连接。

(2)编程实例

该实例分为客户端和服务器端两部分,其中服务器端首先建立起 socket,然后与本地端口进行绑定, 接着就开始接收从客户端的连接请求并建立与它的连接, 接下来,接收客户端发送的消息。客户端则在建立 socket 之后调用 connect()函数来建立连接。

服务器端代码:

#include <sys/types.h> 
#include <sys/socket.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <unistd.h> 
#include <netinet/in.h>
#define PORT               4321 
#define BUFFER_SIZE        1024 
#define MAX_QUE_CONN_NM    5 
 
int main() 
{ 
     struct sockaddr_in server_sockaddr,client_sockaddr; 
     int sin_size,recvbytes; 
     int sockfd, client_fd; 
     char buf[BUFFER_SIZE]; 
      
     /*建立 socket 连接*/ 
     if ((sockfd = socket(AF_INET,SOCK_STREAM,0))== -1) 
     { 
          perror("socket"); 
          exit(1); 
     } 
     printf("Socket id = %d\n",sockfd); 
      
     /*设置 sockaddr_in 结构体中相关参数*/ 
     server_sockaddr.sin_family = AF_INET; 
     server_sockaddr.sin_port = htons(PORT); 
     server_sockaddr.sin_addr.s_addr = INADDR_ANY; 
     bzero(&(server_sockaddr.sin_zero), 8); 
      
     int i = 1;/* 允许重复使用本地地址与套接字进行绑定 */ 
     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); 
      
     /*绑定函数 bind()*/ 
     if (bind(sockfd, (struct sockaddr *)&server_sockaddr,  
                   sizeof(struct sockaddr)) == -1) 
     { 
          perror("bind"); 
          exit(1); 
     } 
     printf("Bind success!\n"); 
      
     /*调用 listen()函数,创建未处理请求的队列*/ 
     if (listen(sockfd, MAX_QUE_CONN_NM) == -1) 
     { 
          perror("listen"); 
          exit(1); 
     } 
     printf("Listening....\n"); 
      
     /*调用 accept()函数,等待客户端的连接*/ 
     if ((client_fd = accept(sockfd,  
                  (struct sockaddr *)&client_sockaddr, &sin_size)) == -1) 
     { 
          perror("accept"); 
          exit(1); 
     } 
      
     /*调用 recv()函数接收客户端的请求*/ 
     memset(buf , 0, sizeof(buf)); 
     if ((recvbytes = recv(client_fd, buf, BUFFER_SIZE, 0)) == -1) 
     { 
          perror("recv"); 
          exit(1); 
     } 
     printf("Received a message: %s\n", buf); 
     close(sockfd); 
     exit(0); 
} 

客户端代码:

/*client.c*/ 
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <netdb.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
 
#define PORT   4321 
#define BUFFER_SIZE 1024 
int main(int argc, char *argv[]) 
{ 
     int sockfd,sendbytes; 
     char buf[BUFFER_SIZE]; 
     struct hostent *host; 
     struct sockaddr_in serv_addr; 
      
     if(argc < 3) 
     { 
          fprintf(stderr,"USAGE: ./client Hostname(or ip address) 
Text\n"); 
          exit(1); 
     } 
      
     /*地址解析函数*/ 
     if ((host = gethostbyname(argv[1])) == NULL) 
     { 
          perror("gethostbyname"); 
          exit(1); 
     } 
      
     memset(buf, 0, sizeof(buf)); 
     sprintf(buf, "%s", argv[2]); 
      
     /*创建 socket*/ 
     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
     { 
          perror("socket"); 
          exit(1); 
     } 
      
     /*设置 sockaddr_in 结构体中相关参数*/ 
     serv_addr.sin_family = AF_INET; 
     serv_addr.sin_port = htons(PORT); 
     serv_addr.sin_addr = *((struct in_addr *)host->h_addr); 
     bzero(&(serv_addr.sin_zero), 8); 
      
     /*调用 connect 函数主动发起对服务器端的连接*/ 
     if(connect(sockfd,(struct sockaddr *)&serv_addr, sizeof(struct sockaddr))== -1)
     { 
          perror("connect"); 
          exit(1); 
     } 
      
     /*发送消息给服务器端*/ 
     if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1) 
     { 
          perror("send"); 
          exit(1); 
     } 
     close(sockfd); 
     exit(0); 
} 
 

在运行时需要先启动服务器端,再启动客户端。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值