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. mysql开启binlog

    mysql开启binlog,至于为什么要开启binlog,可以google下. ## 设置server_id,一般设置为IP server_id= ## 复制过滤:需要备份的数据库名,多个库以逗号分隔 ...

  2. iOS coredata 级联删除

    应用场景如下,每个用户可以设定多个提醒,当删除一个用户时,应当把相关的提醒都删除,而删除一个提醒时,应当把提醒从用户信息中删除. 那么 Profile 应该建立一个如下图的relationship 而 ...

  3. jquery checkbox 限制多选的个数

    2015年11月6日 16:32:49 选中第四个的时候提示超过了3个, 点解alert框取消后, 将最后一个选中的checkbox取消选中 <script> $(document).re ...

  4. ASM:《X86汇编语言-从实模式到保护模式》第13章:保护模式下内核的加载,程序的动态加载和执行

    ★PART1:32位保护模式下内核简易模型 1. 内核的结构,功能和加载 每个内核的主引导程序都会有所不同,因为内核都会有不同的结构.有时候主引导程序的一些段和内核段是可以共用的(事实上加载完内核以后 ...

  5. 【leetcode】Reorder List (middle)

    Given a singly linked list L: L0→L1→…→Ln-1→Ln,reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do thi ...

  6. Tmux的安装、使用与配置

    tmux 安装.使用.配置 因上线需求,故需要使用tumx,方便上线 tmux功能 提供了强大的.易于使用的命令行界面 可横向.纵向分割窗口 窗格可以自由移动和调整大小,或者直接利用四个预设布局之一 ...

  7. 解决At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this log

    pom增加:<dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</art ...

  8. maven入门基础(转)

    maven介绍 maven是构建工具,也是构建管理工具.ant只是构建工具,因为不支持生成站点功能,只有预处理,编译,打包,测试,部署等功能. maven坐标 groupId:项目组织的逆向域名,比如 ...

  9. IT人学习方法论(一):学习方向

    07年的时候曾经讲过一节Webcast,名叫<使您成为Windows专家的一些学习习惯 >.直到最近,还经常收到听众关于这一节课反馈和心得的电子邮件,可见学习方法论是大家非常关心的问题.因 ...

  10. VS2012/2013 停止调试后,无法刷新页面