api有哪些 javasocket_Java Socket编程以及与Linux Socket API关系

Socket 编程(基于Linux)

Socket独立于具体协议的网络编程接口,在ISO模型中,主要位于会话层和传输层之间;在通用的计算机网络五层模型中,主要位于应用层和传输层之间。

Linux Socket

基本上就是BSD Socket

需要使用的头文件

数据类型:#include

函数定义:#include

Socket类型

套接字是一种通信机制,通信两方的一种约定,用套接字中的相关函数来完成通信过程。根据传输内容分为流式套接字、数据报套接字、原始套接字;根据使用方式分为主动套接字和被动套接字。

流式套接字(SOCK_STREAM)

提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。(面向TCP)

数据报套接字(SOCK_DGRAM)

提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失或重复,顺序发送,可能乱序接收。(面向UDP)

原始套接字(SOCK_RAW)

可以对较低层次协议,如IP、ICMP直接访问。

主动套接字和被动套接字

创建方式相同,使用方式不同

等待传入连接的套接字——被动,如服务器套接字

发起连接的套接字——主动,如客户套接字

指明端点地址:创建时不指定,使用时指明:

TCP/IP需要指明协议端口号和IP地址

TCP/IP协议族:PF_INET

TCP/IP的地址族:AF_INET

Linux Socket API函数

socket 创建套接字

connect 建立连接

bind 绑定本机端口

listen 监听端口

accept 接受连接

recv, recvfrom 数据接收

send, sendto 数据发送

close, shutdown 关闭套接字

TCP下通信调用Linux Socket API流程如下:

UDP下通信调用Linux Socket API流程如下:

Linux Socket API函数详解

socket函数

int socket( int domain, int type, int protocol)

功能:创建一个新的套接字,返回套接字描述符

参数说明:

domain:域类型,指明使用的协议栈,如TCP/IP使用的是 PF_INET

type: 指明需要的服务类型, 如:

SOCK_DGRAM: 数据报服务,UDP协议

SOCK_STREAM: 流服务,TCP协议

protocol:一般都取0

举例:s=socket(PF_INET,SOCK_STREAM,0)

connect函数

int connect(int sockfd,struct sockaddr *server_addr,int sockaddr_len)

功能: 同远程服务器建立主动连接,成功时返回0,若连接失败返回-1。

参数说明:

Sockfd:套接字描述符,指明创建连接的套接字

Server_addr:指明远程端点:IP地址和端口号

sockaddr_len :地址长度

bind函数

int bind(int sockfd,struct sockaddr * my_addr,int addrlen)

功能:为套接字指明一个本地端点地址TCP/IP协议使用sockaddr_in结构,包含IP地址和端口号,服务器使用它来指明熟知的端口号,然后等待连接

参数说明:

Sockfd:套接字描述符,指明创建连接的套接字

my_addr:本地地址,IP地址和端口号

addrlen :地址长度

举例:bind(sockfd, (struct sockaddr *)&address, sizeof(address));

listen函数(TCP)

int listen(int sockfd,int input_queue_size)

功能:面向连接的服务器使用它将一个套接字置为被动模式,并准备接收传入连接。用于服务器,指明某个套接字连接是被动的

参数说明:

Sockfd:套接字描述符,指明创建连接的套接字

input_queue_size:该套接字使用的队列长度,指定在请求队列中允许的最大请求数

举例:listen(sockfd,20)

accept函数(TCP)

int accept(int sockfd, void *addr, int *addrlen);

功能:获取传入连接请求,返回新的连接的套接字描述符。为每个新的连接请求创建了一个新的套接字,服务器只对新的连接使用该套接字,原来的监听套接字接受其他的连接请求。新的连接上传输数据使用新的套接字,使用完毕,服务器将关闭这个套接字。

参数说明:

sockfd:套接字描述符,指明正在监听的套接字

addr:提出连接请求的主机地址

addrlen:地址长度

举例:new_sockfd = accept(sockfd, (struct sockaddr *)&address, &addrlen);

UDP下接收与发送

sendto函数

int sendto(int sockfd, const void * data, int data_len, unsigned int flags, struct sockaddr *remaddr,int remaddr_len)

功能:基于UDP发送数据报,返回实际发送的数据长度,出错时返回-1

参数说明:

sockfd:套接字描述符

data:指向要发送数据的指针

data_len:数据长度

flags:一直为0

remaddr:远端地址:IP地址和端口号

remaddr_len :地址长度

举例:sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&address, sizeof(address));

recvfrom函数

int recvfrom(int sockfd, void *buf, int buf_len,unsigned int flags,struct sockaddr *from,int *fromlen);

功能:从UDP接收数据,返回实际接收的字节数,失败时返回-1

参数说明:

sockfd:套接字描述符

buf:指向内存块的指针

buf_len:内存块大小,以字节为单位

flags:一般为0

from:远端的地址,IP地址和端口号

fromlen:远端地址长度

举例:recvfrom(sockfd,buf,8192,0, ,(struct sockaddr *)&address, &fromlen);

TCP下接收与发送

send函数

int send(int sockfd, const void * data, int data_len, unsigned int flags)

功能:在TCP连接上发送数据,返回成功传送数据的长度,出错时返回-1。send会将外发数据复制到OS内核中

参数说明:

sockfd:套接字描述符

data:指向要发送数据的指针

data_len:数据长度

flags:一直为0

举例:send(s,req,strlen(req),0);

recv函数

int recv(int sockfd, void *buf, int buf_len,unsigned int flags);

功能:从TCP接收数据,返回实际接收的数据长度,出错时返回-1。服务器使用其接收客户请求,客户使用它接受服务器的应答。如果没有数据,将阻塞,如果收到的数据大于缓存的大小,多余的数据将丢弃。

参数说明:

sockfd:套接字描述符

Buf:指向内存块的指针

Buf_len:内存块大小,以字节为单位

flags:一般为0

举例:recv(sockfd,buf,8192,0)

close函数

close(int sockfd);

功能:撤销套接字。如果只有一个进程使用,立即终止连接并撤销该套接字,如果多个进程共享该套接字,将引用数减一,如果引用数降到零,则撤销它。

参数说明:

Sockfd:套接字描述符

举例:close(socket_descriptor)

转换函数

1.IP地址转换函数

inet_addr() 点分十进制数表示的IP地址转换为网络字节序的IP地址

inet_ntoa() 网络字节序的IP地址转换为点分十进制数表示的IP地址

2.字节排序函数

htonl 4字节主机字节序转换为网络字节序

ntohl  4字节网络字节序转换为主机字节序

htons 2字节主机字节序转换为网络字节序

ntohs 2字节网络字节序转换为主机字节序

域名解析等相关函数

gethostname 获得主机名

getpeername 获得与套接口相连的远程协议地址

getsockname 获得套接口本地协议地址

gethostbyname 根据主机名取得主机信息

gethostbyaddr 根据主机地址取得主机信息

getprotobyname 根据协议名取得主机协议信息

getprotobynumber 根据协议号取得主机协议信息

getservbyname 根据服务名取得相关服务信息

getservbyport 根据端口号取得相关服务信息

getsockopt/setsockopt 获取/设置一个套接口选项

ioctlsocket 设置套接口的工作方式

java下的TCP socket编程

java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多。套接字Socket已经写好封装在java.net.Socket包里。服务器端有特定的ServerSocket方法。

ServerSocket有以下3个属性:

SO_TIMEOUT:表示等待客户连接的超时时间。一般不设置,会持续等待。

SO_REUSEADDR:表示是否允许重用服务器所绑定的地址。一般不设置,经我的测试没必要,下面会进行详解。

SO_RCVBUF:表示接收数据的缓冲区的大小。一般不设置,用系统默认就可以了。

对于Socket类有如下常用方法:

accept方法用于产生”阻塞”,直到接受到一个连接,并且返回一个客户端的Socket对象实例。”阻塞”是一个术语,它使程序运行暂时”停留”在这个地方,直到一个会话产生,然后程序继续;通常”阻塞”是由循环产生的。

getInputStream方法获得网络连接输入,同时返回一个InputStream对象实例。

getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。

注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。

java与linux api调用关系

TCP服务器端Socket通信流程

创建ServerSocket对象,绑定监听端口。

通过accept()方法监听客户端请求。

连接建立后,通过输入流读取客户端发送的请求信息。

通过输出流向客户端发送响应信息。

关闭响应的资源。

TCP客户端通信流程

创建Socket对象,指明需要连接的服务器的地址和端口号。

连接建立后,通过输出流向服务器发送请求信息。

通过输入流获取服务器响应的信息。

关闭相应资源。

多线程实现服务器与多客户端之间通信步骤

服务器端创建ServerSocket,循环调用accept()等待客户端连接。

客户端创建一个socket并请求和服务器端连接。

服务器端接受客户端请求,创建socket与该客户建立专线连接。

建立连接的两个socket在一个单独的线程上对话。

服务器端继续等待新的连接。

多线程下的TCP服务器端:

package socketLearn;

import java.io.*;

import java.net.ServerSocket;

import java.net.Socket;

public class TcpServerChat {

public static void main(String[] args) throws IOException {

System.out.println("--------Server--------");

ServerSocket server = new ServerSocket(8888);

//1. 指定端口,使用ServerSocket创建服务器

while(true){

//2. 阻塞地等待连接

Socket socket = server.accept();

System.out.println("一个客户端建立了连接");

new Thread(()->{

DataInputStream dis = null;

DataOutputStream dos = null;

BufferedReader br= new BufferedReader(new InputStreamReader(System.in));;

try {

dis = new DataInputStream(socket.getInputStream());

dos = new DataOutputStream(socket.getOutputStream());

} catch (IOException e) {

e.printStackTrace();

}

boolean isRunning = true;

while(isRunning){

try {

//3. 接收消息

String msg = dis.readUTF();

System.out.println("客户端说:"+msg);

//4.返回消息

String reMsg = br.readLine();

dos.writeUTF(reMsg);

dos.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

try {

dis.close();

socket.close();

server.close();

} catch (IOException e) {

e.printStackTrace();

}

}).start();

}

}

}

多线程下的TCP客户端:

package socketLearn;

import java.io.*;

import java.net.Socket;

public class TcpClientChat {

public static void main(String[] args) throws IOException {

System.out.println("--------Client--------");

//1. 建立连接,使用Socket创建客户端

Socket client = new Socket("localhost",8888);

boolean isRunning = true;

BufferedReader console = new BufferedReader((new InputStreamReader(System.in)));

DataOutputStream dos = new DataOutputStream(client.getOutputStream());

DataInputStream dis = new DataInputStream(client.getInputStream());

while(isRunning){

//2. 客户端发送消息

String msg = console.readLine();

dos.writeUTF(msg);

dos.flush();

//3. 获取消息

msg = dis.readUTF();

System.out.println("服务器说:"+msg);

}

dos.close();

dis.close();

client.close();

}

}

正常来说,客户端打开一个输出流,如果不做约定,也不关闭它,那么服务端永远不知道客户端是否发送完消息,那么服务端会一直等待下去,直到读取超时。

通过socket关闭

关闭客户端socket,服务器端可执行后续操作,弊端也很明显,客户端不能再次发送消息也不能接收消息,而且要再次发送必须再次创建socket连接

socket关闭输出流

socket.shutdownOutput();

注意不能使用outputStream.close(),若用该法关闭了输出流,那么相应的Socket也将关闭,和直接关闭Socket一个性质。

3. 通过约定的符号

双方约定一个字符或者一个短语,来当做消息发送完成的标识,通常这么做就需要改造读取方法(读取的循环条件)。

4. 通过指定长度

5. 使用DataInputStream、DataOutputStream对socket.getOutputStream,socket.getInputStream进行包装

### UDP Socket编程

* DatagramSocket:用于发送或接收数据包的套接字

* DatagramPacket;数据包

* 不需要利用IO流实现数据的传输每个数据发送单元被统一封装成数据包的方式,发送方将数据包发送到网络中,数据包在网络中去寻找他的目的地。

#### UDP接收方

1、使用DatagramSocket 指定端口创建接收端

2、准备容器封装成DatagramPacket包裹

3、阻塞式接收包裹receive(DatagramPacket p)

4、分析数据byte[] getData();getLength();

5、释放资源

```java

public class UdpServer {

public static void main(String[] args) throws Exception{

System.out.println("接收方启动中...");

DatagramSocket server = new DatagramSocket(9999);

byte[] container = new byte[1024*60];

DatagramPacket packet = new DatagramPacket(container, 0,container.length);

server.receive(packet);

byte[] datas = packet.getData();

int len = packet.getLength();

System.out.println(new String(datas,0,len,"UTF-8"));

server.close();

}

}

UDP发送方

1、使用DatagramSocket 指定端口创建发送端

2、准备数据一定转成字节数组

3、封装成DatagramPacket包裹,需要指定目的地4、发送包裹send(DatagramPacket p)

5、释放资源

public class UdpClient {

public static void main(String[] args) throws Exception{

System.out.println("发送方启动中...");

DatagramSocket client = new DatagramSocket(8888);

String data = "改革春风吹满地";

byte[] datas = data.getBytes();

DatagramPacket packet = new DatagramPacket(datas, 0,datas.length,

new InetSocketAddress("localhost",9999));

client.send(packet);

client.close();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值