一个socket的基础例子
2013-06-28 00:50
316 查看
我不得不说socket编程对于我来说是很复杂的,以前总是说socket,但到现在来说还是没有把他弄懂,即使当时记得了但过了几天又忘记了,所以需要常常看才能牢记。
socket编程的基础函数有socket(),bind(), listen(),accept(),send(),sendto(),recv(),recvfrom()根据客户端还是服务端不一样,针对udp,tcp又是不一样的,先对这几个函数进行说明
socket()------该函数用于建立一个socket连接,可以指定socket类型等信息,在建立socket连接之后,可以对sockaddr或sockaddr_in结构体进行初始化,来保存所建立的socket
地址信息
bind()---------用于将本地ip绑定到端口号,绑定其他ip不能成功,主要用于TCP中,在upd中则没有必要
listen()--------在创建套接字和绑定地址之后需要在该套接字上接受新的请求,listen()可以用来创建一个等待队列,用于存放未处理的客户端请求
accept()-------服务端调用listen之后,调用此函数等待并接收客户端的请求,通常他从listen()函数创建的等待队列中取出第一个未处理的连接请求
connetc()------在TCP中用于bind()之后的客户端用于与服务器建立连接,而在UDP中由于没有bind()函数,这个connect函数有点类似于bind()函数的作用
recv(),recv()---用于数据的发送和接收,在udp中可以在connet()建立连接之后再使用
sendto(),recvfrom()---在TCP中作用等同于send(),recv(),而在UDP中可以用在之前没有使用connect()的情况,这两个函数可以自动寻找指定地址并进行连接
服务器和客户端使用TCP协议的流程如下:
![](http://img.blog.csdn.net/20130626222957500?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
对于客户端有时不需要进行bind()调用,http://blog.csdn.net/smilestone322/article/details/8449165
服务器和客户端使用UDP协议的流程如下:
![](http://img.blog.csdn.net/20130626223249015?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
下面是各个函数的使用语法:
socket()使用语法:
![](http://img.blog.csdn.net/20130626225008437?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20130626225206000?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
bind()函数的使用语法:
![](http://img.blog.csdn.net/20130626225416406?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
端口号和地址在my_addr中给出,如果不指定地址则内核随意分配一个临时端口给程序
listen()函数语法如下:
![](http://img.blog.csdn.net/20130626225730375?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
accept()函数语法如下:
![](http://img.blog.csdn.net/20130626225845671?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20130626225908390?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
connect()函数语法如下:
![](http://img.blog.csdn.net/20130626230032906?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
send()函数语法:
![](http://img.blog.csdn.net/20130626230143156?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
recv函数语法:
![](http://img.blog.csdn.net/20130626230227531?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
sendto语法:
![](http://img.blog.csdn.net/20130626230357359?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20130626230405937?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
recvfrom函数语法:
![](http://img.blog.csdn.net/20130626230556906?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
下面是一个c/s的例子
server.c
对应client端的实例如下:
执行客户端:
![](http://img.blog.csdn.net/20130628004818984?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenp5b3VjYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
服务端将会接收消息:
socket编程的基础函数有socket(),bind(), listen(),accept(),send(),sendto(),recv(),recvfrom()根据客户端还是服务端不一样,针对udp,tcp又是不一样的,先对这几个函数进行说明
socket()------该函数用于建立一个socket连接,可以指定socket类型等信息,在建立socket连接之后,可以对sockaddr或sockaddr_in结构体进行初始化,来保存所建立的socket
地址信息
bind()---------用于将本地ip绑定到端口号,绑定其他ip不能成功,主要用于TCP中,在upd中则没有必要
listen()--------在创建套接字和绑定地址之后需要在该套接字上接受新的请求,listen()可以用来创建一个等待队列,用于存放未处理的客户端请求
accept()-------服务端调用listen之后,调用此函数等待并接收客户端的请求,通常他从listen()函数创建的等待队列中取出第一个未处理的连接请求
connetc()------在TCP中用于bind()之后的客户端用于与服务器建立连接,而在UDP中由于没有bind()函数,这个connect函数有点类似于bind()函数的作用
recv(),recv()---用于数据的发送和接收,在udp中可以在connet()建立连接之后再使用
sendto(),recvfrom()---在TCP中作用等同于send(),recv(),而在UDP中可以用在之前没有使用connect()的情况,这两个函数可以自动寻找指定地址并进行连接
服务器和客户端使用TCP协议的流程如下:
对于客户端有时不需要进行bind()调用,http://blog.csdn.net/smilestone322/article/details/8449165
服务器和客户端使用UDP协议的流程如下:
下面是各个函数的使用语法:
socket()使用语法:
bind()函数的使用语法:
端口号和地址在my_addr中给出,如果不指定地址则内核随意分配一个临时端口给程序
listen()函数语法如下:
accept()函数语法如下:
connect()函数语法如下:
send()函数语法:
recv函数语法:
sendto语法:
recvfrom函数语法:
下面是一个c/s的例子
server.c
#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)) ; //绑定ip与端口号 if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof (struct sockaddr)) == -1) { perror("bind error") ; exit(1) ; } printf("bind success\n") ; /*调用listen()函数,创建未处理请求队列*/ if (listen(sockfd, MAX_QUE_CONN_NM) == -1) { perror("listen error\n") ; exit (1) ; } printf("listen....\n") ; //等待客户连接,此处返回客户端的socket描述符 if((client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, &sin_size)) == -1) { perror("accept") ; exit(1) ; } memset(buf, 0, sizeof(buf)) ; /*调用recv()函数接收客户端请求*/ if ((recvbytes = recv(client_fd, buf, BUFFER_SIZE, 0)) == -1) { perror("recv") ; exit(1) ; } printf("recevie a message :%s\n", buf) ; close(sockfd) ; exit(0) ; }
对应client端的实例如下:
#include <error.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <netdb.h> #include <netinet/in.h> #include <sys/types.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) ; } //由主机名获得ip if ((host = gethostbyname(argv[1])) == NULL) { perror("gethostbyname") ; exit(1) ; } memset(buf, 0, sizeof(buf)) ; sprintf(buf, "%s", argv[2]) ; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) ==-1) { perror("socket") ; exit(1) ; } 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) ; if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(struct sockaddr)) == -1) { perror("connetc") ; exit(1) ; } if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1) { perror("send") ; exit (1) ; } close(sockfd) ; exit(0) ; }
执行客户端:
服务端将会接收消息:
相关文章推荐
- 非阻塞方式下Socket读取数据的一个例子
- 一个 Java 的 Socket 服务器和客户端通信的例子
- 一个Android Socket的例子
- 一个很基础的DOM例子
- SQL优化基础 使用索引(一个小例子)
- 一个SocketService例子
- 一个关于linux socket的简单例子
- 一个Socket服务的例子! 请高手指点无法捕捉的输出如何修改?
- Android基于客户端和服务器的Socket编程例子之Socket基础通讯--socket模型使用
- windows下的socket编程【清晰,好用的一个例子~】
- 一个select接收socket数据的例子
- Java WebSocket编程——一个简单的例子(编程式)
- 一个Socket编程的例子
- symbian rsocket 的一个例子
- socket编程——一个简单的例子(转)
- 一个大型例子搞定 Javascript 的数组基础知识 ——总结《Javascript 权威指南》第六版数组基础知识
- Python里的例子:一个基础验证相关的教程
- HTML基础:一个例子熟悉常用标签
- Socket通信基础介绍及例子
- 多个客户端使用Socket通过一个服务器进行交互的小例子