socket: 也称作套接字,应用程序通常通过套接字向网络发出请求或者应答网络请求。

常用的套接字API函数:

1、socket():

函数原型为:int socket(int domain, int type, int protocol);

函数参数说明:

domain: 为创建的套接字指定协议集,例如:AF_INET(表示IPv4网络协议)、AF_INET6(表示IPv6)、AF_UNIX或者AF_LOCAL(表示本地套接字)。

type:SOCK_STREAM(可靠地面向流服务或流套接字)、SOCK_DGRAM(数据报文或者数据报文套接字)、SOCK_SEQPACKET(可靠的连续数据包服务)、SOCK_RAW(在网络层之上的原始协议)。

protocol:指定实际使用的传输协议。最常见的就是IPPROTO_TCP、IPPROTO_SCTP、IPPROTO_UDP、IPPROTO_DCCP。这些协议都在<netinet/in.h>中有详细说明。
如果该项为“0”的话,即根据选定的domain和type选择使用缺省协议。

返回值:如果发生错误,则返回-1,否则返回的是一个代表新分配的描述符的整数。

2、bind():

函数原型:bind()为一个套接字分配地址,当使用socket()创建套接字后,只赋予其所使用的协议,并未分配地址。在接受其它主机的连接前,必须先调用bind()为套接字分配一个地址。

函数原型为:int bind(int sockfd, const struct sockaddr *my_addr,  socklen_t addrlen);

函数参数说明:

sockfd:表示使用bind函数的套接字描述符。

my_addr:指向sockaddr结构(用于表示所分配地址)的指针。

addrlen:用socklen_t字段指定了sockaddr结构的长度。

返回值:如果发生错误,则返回-1,否则返回0。

3、listen():

当socket和一个地址绑定之后,listen()函数会开始监听可能的连接请求,但这是只能在有可靠数据流保证的时候使用,例如数据类型(SOCK_STREAM,SOCK_SEQPACKET)。

函数原型:int listen(int sockfd, int backlog);

函数参数说明:

sockfd:一个socket的描述符。

backlog:一个决定监听队列大小的整数,当有一个请求来到时,就会进入此监听队列,当队列满后,新的连接请求就会返回错误。

返回值:0表示成功,-1表示错误。

4、accept():

当应用程序监听来自其他主机的面对数据流的连接时,通过事件(比如Unix select()系统调用)通知它。必须用 accept()函数初始化连接。 Accept() 为每个连接创立新的套接字并从监听队列中移除这个连接。

函数原型:int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)。

函数参数说明:

sockfd:监听的套接字描述符。

cliaddr:指向sockaddr结构体的指针,客户机地址信息。

addrlen:指向socklen_t的指针,确定客户机地址结构体的大小。

返回值:返回新的套接字描述符,如果出错就返回-1。进一步的通信必须通过这个套接字。

5、connect():

connect()系统调用为一个套接字设置参数连接,参数有文件描述符和主机地址。

有些类型的套接字是无连接的,大多数是使用UDP协议。对于这些套接字,连接时这样的:默认发送和接收数据的主机由给定的地址确定,可以使用 send()和 recv()。

返回值: 返回-1表示出错,0表示成功。

6、select():用于修整有如下情况的套接字列表:准备读,准备写或者是用错误。

7、poll():用于检查套接字的状态。套接字可以被测试,看是否可以写入、读取或是用错误。

8、getsockopt():用于查询指定的套接字一个特定的套接字选项的当前值。

9、setsockopt():用于为指定的套接字设定一个特定的套接字选项。

使用TCP的服务器:

设置一个简单的TCP服务器的步骤:

1、调用socket函数建立套接字。

2、调用bind函数把套接字绑定到一个监听端口上。注意bind函数需要接受一个sockaddr_in结构体作为参数,因此在调用bind函数之前, 程序要先声明一个 sockaddr_in结构体,用memset函数将其清零,然后将其中的sin_family设置为AF_INET,接下来,程序需要设置其sin_port成员变量,即监听端口。需要说明的是,sin_port中的端口号需要以网络字节序存储,因此需要调用htons函数对端口号进行转换(函数名是"host
to network short"的缩写)。

3、调用listen函数,使该套接字成为一个处在监听状态的套接字。

4、服务器可以通过accept函数接受客户端的连接请求。若没有收到连接请求,accept函数将不会返回并阻塞程序的执行。接收到连接请求后,accept函数会为该连接返回一个套接字描述符。accept函数可以被多次调用来接受不同客户端的连接请求,而且之前的连接仍处于监听状态——直到其被关闭为止。

5、服务器可以通过对send,recv或者对write,read等函数的调用来同客户端进行通信。

6、对于一个不再需要的套接字,可以使用close函数关闭它。

代码如下:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> int main()
{
struct sockaddr_in stSockAddr; //服务器网络地址结构体
//创建服务器端套接字--IPv4协议,面向可靠的字节流服务,TCP协议
int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (SocketFD == -1) {
perror("can not create socket");
exit(EXIT_FAILURE);
} memset(&stSockAddr, 0, sizeof(struct sockaddr)); stSockAddr.sin_family = AF_INET; //设置为IP通信
stSockAddr.sin_port = htons(1200);//服务器的端口号
stSockAddr.sin_addr.s_addr = INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上
//将套接字绑定到服务器的网络地址上
if (bind(SocketFD, (const struct sockaddr *)&stSockAddr, sizeof(struct sockaddr_in)) == -1) {
perror("error bind failed");
close(SocketFD);
exit(EXIT_FAILURE);
} //监听可能的连接请求,监听队列长度为10
if (listen(SocketFD, 10) == -1) {
perror("error listen failed");
close(SocketFD);
exit(EXIT_FAILURE);
} while (true) {
//accept()为每个连接创立新的套接字并从监听队列中移除这个连接,其返回值为新的套接字描述符
int ConnectFD = accept(SocketFD, NULL, NULL);
if (ConnectFD < 0) {
perror("error accept failed");
close(SocketFD);
exit(EXIT_FAILURE);
}
//调用shutdown只是进行了TCP断开,并没有释放文件描述符
shutdown(ConnectFD, SHUT_RDWR);
close(ConnectFD);
} close(SocketFD);
return 0;
}

使用TCP的客户端:

建立一个客户机的步骤如下:

1、调用socket()建立套接字。

2、用connect()连接到服务器,类似服务器端的操作,将sin_family设为AF_INET,sin_port设为服务器的监听端口(依然要以网络字节序),sin_addr设为服务器IP地址的(还是要用网络字节序)的sockaddr_in作为参数传入。

3、用send() 和 recv() 或者 write() 和 read()进行通信。

4、用close()终止连接。如果调用fork(), 每个进程都要用close()。

代码如下:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> int main()
{
struct sockaddr_in stSockAddr;
int Res; int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (SocketFD == -1) {
perror("can not create socket");
exit(EXIT_FAILURE);
} memset(&stSockAddr, 0, sizeof(struct sockaddr_in)); stSockAddr.sin_family = AF_INET;
stSockAddr.sin_port = (1200);
Res = inet_pton(AF_INET, "192.168.1.4", &stSockAddr.sin_addr);
if (Res < 0) {
perror("error: first parameter is not a valid address family");
close(SocketFD);
exit(EXIT_FAILURE);
} else if (Res == 0) {
perror("second parameter does not contain valid ipaddress");
close(SocketFD);
exit(EXIT_FAILURE);
} if (connect(SocketFD, (const struct sockaddr *)&stSockAddr, sizeof(struct sockaddr_in)) == -1) {
perror("connect failed");
close(SocketFD);
exit(EXIT_FAILURE);
} shutdown(SocketFD, SHUT_RDWR);
close(SocketFD);
return 0;
}

使用UDP的服务器:

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> int main()
{
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in sa;
char buffer[1024];
ssize_t recsize;
socklen_t fromlen; memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons(7654); if (bind(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr))) {
perror("error bind failed");
close(sock);
exit(EXIT_FAILURE);
} while (true) {
puts("recv test...");
//用recvfrom接收给UDP端口7654的数据包
recsize = recvfrom(sock, (void *)buffer, 1024, 0, (struct sockaddr *)&sa, &fromlen);
if (recsize < 0) {
puts("....");
} printf("recsize : %d\n", recsize);
sleep(1);
printf("datagram : %s\n", buffer);
}
return 0;
}



使用UDP的客户端:

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> int main()
{
int sock;
struct sockaddr_in sa;
int bytes_sent, buffer_length;
char buffer[100]; buffer_length = snprintf(buffer, sizeof(buffer), "Hello World\r\n"); sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock == -1) {
puts("can not create socket");
exit(EXIT_FAILURE);
} memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
//回环地址127.0.0.1
sa.sin_addr.s_addr = htonl(0x7f000001);
sa.sin_port = htons(7654); bytes_sent = sendto(sock, buffer, buffer_length, 0, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
if (bytes_sent < 0) {
puts("Error sending packet");
}
close(sock);
return 0;
}

socket编程学习的更多相关文章

  1. socket编程学习step1

    socket学习参考链接,赞一个:http://blog.csdn.net/hguisu/article/details/7445768 sockets(套接字)编程有三种,流式套接字(SOCK_ST ...

  2. JAVA Socket 编程学习笔记(二)

    在上一篇中,使用了 java Socket+Tcp/IP  协议来实现应用程序或客户端--服务器间的实时双向通信,本篇中,将使用 UDP 协议来实现 Socket 的通信. 1. 关于UDP UDP协 ...

  3. JAVA Socket 编程学习笔记(一)

    1. Socket 通信简介及模型 Java Socket 可实现客户端--服务器间的双向实时通信.java.net包中定义的两个类socket和ServerSocket,分别用来实现双向连接的cli ...

  4. Socket编程学习之道:揭开Socket编程的面纱

    对TCP/IP.UDP.Socket编程这些词你不会非常陌生吧?随着网络技术的发展.这些词充斥着我们的耳朵. 那么我想问: 1.         什么是TCP/IP.UDP? 2.         S ...

  5. LInux下socket编程学习笔记

    1.socket套接字: socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模 ...

  6. 记一次:Windows的Socket编程学习和分析过程

    Socket编程依赖于:WS2_32.dll --- 服务端 --- .导入我们需要的函数 #incldue <windows.h> //#include<WinSock2.h> ...

  7. Android Socket编程学习笔记

    http://blog.csdn.net/eyu8874521/article/details/8847173 度娘给出的描述:通常也称作"套接字",用于描述IP地址和端口,是一个 ...

  8. C++的socket编程学习

    前言 不得不承认作为一个前端开发,仍有一个后台开发的梦.从socket通信开始学习,在工作之余补充学习点相关知识,记录下学习的过程. 服务端 服务器代码如下,在设置listen之后,通过accept获 ...

  9. BSD socket编程学习

    1.socket简介 BSD是实现TCP/IP协议通信的软件系统,socket是应用编程接口,为app提供使用TCP/IP协议通信的接口. 网络层IP提供点到点服务(IP地址标识),传输层TCP和UD ...

随机推荐

  1. 【leetcode】Convert Sorted Array to Binary Search Tree

    Convert Sorted Array to Binary Search Tree Given an array where elements are sorted in ascending ord ...

  2. linux grep 查找字符串

    2015年8月27日 12:04:58 在当前文件夹查找 public function abc() grep -re 'public function abc\b' . // 可以不加e, 适合函数 ...

  3. INNODB自增主键的一些问题

    背景: 自增长是一个很常见的数据属性,在MySQL中大家都很愿意让自增长属性的字段当一个主键.特别是InnoDB,因为InnoDB的聚集索引的特性,使用自增长属性的字段当主键性能更好,这里要说明下自增 ...

  4. WebRequest 获取网页乱码

    问题:在用WebRequest获取网页源码时得到的源码是乱码. 原因:1,编码不对 解决办法:设置对应编码 WebRequest request = WebRequest.Create(Url);We ...

  5. HDU 4945 2048(dp)

    题意:给n(n<=100,000)个数,0<=a[i]<=2048 .一个好的集合要满足,集合内的数可以根据2048的合并规则合并成2048 .输出好的集合的个数%998244353 ...

  6. 开始使用 Fresco

    如果你仅仅是想简单下载一张网络图片,在下载完成之前,显示一张占位图,那么简单使用 SimpleDraweeView 即可. 在加载图片之前,你必须初始化Fresco类.你只需要调用Fresco.ini ...

  7. SQL Server 2008 R2 安装出错:Could not open key

    安装Sql Server 2008 R2 企业版出现错误提示无法继续安装,错误提示为: Could not open key: UNKNOWN\Components\7ABFE44842C12B390 ...

  8. IOS - SDWebImage 非ARC 问题

    非arc项目中使用SDWebImage类库 1.添加类库引用    (1)ImageIO.framework    (2)MapKit.framework 2.在targets->build P ...

  9. [Android ] linux命令英文缩写的含义(方便记忆)

    du -sh */ reference to : http://blog.chinaunix.net/uid-27164517-id-3299073.html linux常用命令的英文单词缩写 命令缩 ...

  10. August 20th 2016 Week 34th Saturday

    Everything you see exists together in a delicate balance. 你所看到的一切都处于微妙的平衡中. Seeking for balance in l ...