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); }
在运行时需要先启动服务器端,再启动客户端。
- Socket编程实践(1)
- ipv6 socket编程实践
- socket编程实践
- Android Socket编程实践
- Socket编程实践(2) --Socket编程导引
- Socket编程实践(2) --Socket编程导引
- Socket编程实践(2) --Socket编程导引
- Socket编程实践模拟通信
- Socket编程实践(3) --Socket API
- Socket编程实践(3) --Socket API
- Socket编程实践(3) --Socket API
- Socket编程实践(12) --UDP编程基础
- Socket编程实践(11) --UDP编程基础
- Socket编程实践(12) --UDP编程基础
- Socket编程实践 -- Select I/O复用
- Socket编程实践(1) --TCP/IP简述
- Socket编程实践(6) --TCP服务端注意事项
- Socket编程实践(13) --UNIX域协议
- 深入理解javascript原型和闭包
- 全局变量与强符号和弱符号
- 金融类期刊
- RPC框架之-DUBBO(二)负载均衡
- 使用JMeter创建数据库(Mysql)测试
- socket编程实践
- mysql中使用正则表达式查询
- Java学习-使用javac,java命令运行程序
- linux命令总结(三)
- Eclipse中用两个控制台测试网络通信程序
- 洛谷 P1518 两只塔姆沃斯牛
- 多线程二
- JavaScript 控制(改变)canvas(画布)的大小
- 162.Set Matrix Zeroes-矩阵归零(中等题)