socket编程实践

来源:互联网 发布:java 连接池框架 编辑:程序博客网 时间:2024/06/02 21:00

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); }  

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


0 0
原创粉丝点击