1.socket编程:socket编程,网络字节序,函数介绍,IP地址转换函数,sockaddr数据结构,网络套接字函数,socket相关函数,TCP server和client




Socket编程

socket这个词可以表示很多概念:

在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP

地址+端口号”就称为socket。

在TCP协议中,建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socket
pair就唯一标识一个连接。socket本身有“插座”的意思,因此用来描述网络连

接的一对一关系。

TCP/IP协议最早在BSD UNIX上实现,为TCP/IP协议设计的应用层编程接口称为socket

API。

本章的主要内容是socketAPI,主要介绍TCP协议的函数接口,最后介绍UDP协议和UNIX
Domain Socket的函数接口。

图11.1:socketAPI

2
网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的

多字节数据相对于文件中的偏移地址也有大端小端之分。网络数据流同样有大端小端之分,

那么如何定义网络数据流的地址呢?发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存,因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。

   
TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。例如上一节的UDP

段格式,地址0-1是16位的源端口号,如果这个端口号是1000(0x3e8),则地址0是0x03,

地址1是0xe8,也就是先发0x03,再发0xe8,这16位在发送主机的缓冲区中也应该是低地址存0x03,高地址存0xe8。但是,如果发送主机是小端字节序的,这16位被解释成0xe803,而不是1000。因此,发送主机把1000填到发送缓冲区之前需要做字节序的转换。同样地,接收主机如果是小端字节序的,接到16位的源端口号也要做字节序的转换。如果主机是大端字节序的,发送和接收都不需要做转换。同理,32位的IP地址也要考虑网络字节序和主机字节序的问题。

 

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

3
函数介绍

A
依赖的头文件

#include <arpa/inet.h>

B
函数声明

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

h表示host,n表示network,l表示32位长整数,s表示16位短整数。

如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。

 

uint32_t htonl(uint32_t hostlong);

名称:

htonl

功能:

The htonl() function converts the unsigned integer hostlong 
from  host byte order to network byte order

头文件:

#include <arpa/inet.h>

函数原形:

uint32_t htonl(uint32_t hostlong);

参数:

 

返回值:

 

 

uint16_t htons(uint16_t hostshort);

名称:

htons

功能:

The htons() function converts the unsigned short integer hostshort from

host byte order to network byte order.

头文件:

#include <arpa/inet.h>

函数原形:

uint16_t htons(uint16_t hostshort);

参数:

 

返回值:

 

 

uint32_t ntohl(uint32_t netlong);

名称:

ntohl

功能:

The ntohl() function converts the unsigned integer netlong from network

byte order to host byte order.

头文件:

#include <arpa/inet.h>

函数原形:

uint32_t ntohl(uint32_t netlong);

参数:

 

返回值:

 

 

uint16_t ntohs(uint16_t netshort);

名称:

ntohs

功能:

The ntohs() function converts the unsigned short integer netshort from

network byte order to host byte order.

头文件:

#include <arpa/inet.h>

函数原形:

uint16_t ntohs(uint16_t netshort);

参数:

 

返回值:

 

 

4 IP地址转换函数

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

int inet_aton(const char *cp, structin_addr *inp);

in_addr_t inet_addr(const char *cp);

char *inet_ntoa(struct in_addr in);

只能处理IPv4的ip地址

不可重入函数

注意参数是struct in_addr

 

现在

#include <arpa/inet.h>

int inet_pton(int af, const char *src, void*dst);

const char *inet_ntop(int af, const void*src, char *dst, socklen_t size);

支持IPv4和IPv6

可重入函数

 

其中inet_pton和inet_ntop不仅可以转换IPv4的in_addr,还可以转换IPv6的in6_addr,因此函数接口是void*addrptr

 

5 sockaddr数据结构

   
strcutsockaddr 很多网络编程函数诞生早于IPv4协议,那时候都使用的是sockaddr结

构体,为了向前兼容,现在sockaddr退化成了(void
*)的作用,传递一个地址给函数,至

于这个函数是sockaddr_in还是sockaddr_in6,由地址族确定,然后函数内部再强制类型转

化为所需的地址类型

图 11.2:sockaddr数据结构

struct sockaddr {

sa_family_t sa_family; /* address family, AF_xxx */

char sa_data[14]; /* 14 bytes of protocol address */

};

 

struct sockaddr_in {

__kernel_sa_family_t sin_family; /* Address family */

__be16 sin_port; /* Port number */

struct in_addr sin_addr; /* Internet address */

/* Pad to size of `struct sockaddr'. */

unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -

sizeof(unsigned short int) - sizeof(struct in_addr)];

};

 

/* Internet address. */

struct in_addr {

__be32 s_addr;

};

 

struct sockaddr_in6 {

unsigned short int sin6_family; /* AF_INET6*/

__be16 sin6_port; /* Transport layer port # */

__be32 sin6_flowinfo; /* IPv6 flow information */

struct in6_addr sin6_addr; /* IPv6 address */

__u32 sin6_scope_id; /* scope id (new in RFC2553) */

};

 

struct in6_addr {

union {

__u8 u6_addr8[16];

__be16 u6_addr16[8];

__be32 u6_addr32[4];

} in6_u;

#define s6_addr in6_u.u6_addr8

#define s6_addr16 in6_u.u6_addr16

#define s6_addr32 in6_u.u6_addr32

};

 

#define UNIX_PATH_MAX 108

struct sockaddr_un {

__kernel_sa_family_t sun_family; /* AF_UNIX */

char sun_path[UNIX_PATH_MAX]; /* pathname */

};

 

Pv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包

括16位端口号和32位IP地址,IPv6地址用sockaddr_in6结构体表示,包括16位端口号、128位IP地址和一些控制字段。UNIX
Domain Socket的地址格式定义在sys/un.h中,用sockaddr_un结构体表示。各种socket地址结构体的开头都是相同的,前16位表示整个结构体的长度(并不是所有UNIX的实现都有长度字段,如Linux就没有),后16位表示地址类型。IPv4、IPv6和Unix
Domain Socket的地址类型分别定义为常数AF_INET、AF_INET6、AF_UNIX。这样,只要取得某种sockaddr结构体的首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容。因此,socket
API可以接受各种类型的sockaddr结构体指针做参数,例如bind、accept、connect等函数,这些函数的参数应该设计成void
*类型以便接受各种类型的指针,但是sock API的实现早于ANSI C标准化,那时还没有void
*类型,因此这些函数的参数都用struct sockaddr *类型表示,在传递参数之前要强制类型转换一下,例如:

struct sockaddr_in servaddr;

/* initialize servaddr */

bind(listen_fd,(struct sockaddr*)&servaddr,sizeof(servaddr));

 

6
网络套接字函数

A socket

#include <sys/types.h>

#include <sys/socket.h>

 

int socket(int domain,int types,intprotocol);

 

domain:

AF_INET
这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址

AF_INET6
与上面类似,不过是来用IPv6的地址

AF_UNIX
本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用

 

type:

SOCK_STREAM
这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。

SOCK_DGRAM
这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。

SOCK_SEQPACKET
这个协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。

SOCK_RAW
这个socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)

SOCK_RDM
这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包的顺序

 

protocol:

0
默认协议

返回值:

成功返回一个新的文件描述符,失败返回-1,设置errno

 

socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,应用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调用出错则返回-1。对于IPv4,domain参数指定为AF_INET。对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输协议。如果是UDP协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议。protocol参数的介绍从略,指定为0即可。

 

7 bind

A
依赖的头文件

#include <sys/types.h> /* See NOTES*/

#include <sys/socket.h>

B
函数声明

int bind(int sockfd, const struct sockaddr*addr, socklen_t addrlen);

sockfd:

   socket文件描述符

addr:

构造出IP地址加端口号

addrlen:

   sizeof(addr)长度

返回值:

   
成功返回0,失败返回-1,设置errno

 

服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序

的地址和端口号后就可以向服务器发起连接,因此服务器需要调用bind绑定一个固定的网络地址和端口号。

   
bind()的作用是将参数sockfd和addr绑定在一起,使sockfd这个用于网络通讯的文件

描述符监听addr所描述的地址和端口号。前面讲过,struct
sockaddr *是一个通用指针类

型,addr参数实际上可以接受多种协议的sockaddr结构体,而它们的长度各不相同,所以需要第三个参数addrlen指定结构体的长度。如:

 

struct sockaddr_in servaddr;

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr =htonl(INADDR_ANY);

servaddr.sin_port = htons(8000);

首先将整个结构体清零,然后设置地址类型为AF_INET,网络地址为INADDR_ANY,这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP地址,端口号为8000。

 

8 listen

#include <sys/types.h> /* See NOTES*/

#include <sys/socket.h>

 

int listen(int sockfd, int backlog);

sockfd:

socket文件描述符

backlog:

排队建立3次握手队列和刚刚建立3次握手队列的链接数和

 

查看系统默认backlog

cat /proc/sys/net/ipv4/tcp_max_syn_backlog

典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的

accept()返回并接受这个连接,如果有大量的客户端发起连接而服务器来不及处理,尚未

accept的客户端就处于连接等待状态,listen()声明sockfd处于监听状态,并且最多允许有

backlog个客户端处于连接待状态,如果接收到更多的连接请求就忽略。listen()成功返回

0,失败返回-1。

 

9
 accept

#include <sys/types.h> /* See NOTES*/

#include <sys/socket.h>

int accept(int sockfd, struct sockaddr*addr, socklen_t *addrlen);

sockdf:

socket文件描述符

addr:

传出参数,返回链接客户端地址信息,含IP地址和端口号

addrlen:

传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小

返回值:

成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno

 

三方握手完成后,服务器调用accept()接受连接,如果服务器调用accept()时还没有

客户端的连接请求,就阻塞等待直到有客户端连接上来。addr是一个传出参数,accept()

返回时传出客户端的地址和端口号。addrlen参数是一个传入传出参数(value-result
argument),传入的是调用者提供的缓冲区addr的长度以避免缓冲区溢出问题,传出的是客

户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区)。如果给addr参数传

NULL,表示不关心客户端的地址。

 

我们的服务器程序结构是这样的:

while (1) {

cliaddr_len = sizeof(cliaddr);

connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&cliaddr_len);

n = read(connfd, buf, MAXLINE);

......

close(connfd);

}

 

整个是一个while死循环,每次循环处理一个客户端连接。由于cliaddr_len是传入传出

参数,每次调用accept()之前应该重新赋初值。accept()的参数listenfd是先前的监听文件

描述符,而accept()的返回值是另外一个文件描述符connfd,之后与客户端之间就通过这个

connfd通讯,最后关闭connfd断开连接,而不关闭listenfd,再次回到循环开头listenfd仍

然用作accept的参数。accept()成功返回一个文件描述符,出错返回-1。

 

10 connect

#include <sys/types.h> /* See NOTES*/

#include <sys/socket.h>

int connect(int sockfd, const structsockaddr *addr, socklen_t addrlen);

sockdf:

socket文件描述符

addr:

传入参数,指定服务器端地址信息,含IP地址和端口号

addrlen:

传入参数,传入sizeof(addr)大小

返回值:

成功返回0,失败返回-1,设置errno

 

客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址。connect()成功返回0,出错返回-1。

 

11 C/S模型-TCP

   
下图是基于TCP协议的客户端/服务器程序的一般流程:

图11.3: TCP协议通讯流程

服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于

监听端口的状态,客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服

务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK

段,服务器收到后从accept()返回。

数据传输的过程:

建立连接后,TCP协议提供全双工的通信服务,但是一般的客户端/服务器程序的流程是由客户端主动发起请求,服务器被动处理请求,一问一答的方式。因此,服务器从accept()

返回后立刻调用read(),读socket就像读管道一样,如果没有数据到达就阻塞等待,这时客

户端调用write()发送请求给服务器,服务器收到后从read()返回,对客户端的请求进行处

理,在此期间客户端调用read()阻塞等待服务器的应答,服务器调用write()将处理结果发

回给客户端,再次调用read()阻塞等待下一条请求,客户端收到后从read()返回,发送下一

条请求,如此循环下去。

如果客户端没有更多的请求了,就调用close()关闭连接,就像写端关闭的管道一样,

服务器的read()返回0,这样服务器就知道客户端关闭了连接,也调用close()关闭连接。注

意,任何一方调用close()后,连接的两个传输方向都关闭,不能再发送数据了。如果一方

调用shutdown()则连接处于半关闭状态,仍可接收对方发来的数据。

在学习socket API时要注意应用程序和TCP协议层是如何交互的:
*应用程序调用某个

socket函数时TCP协议层完成什么动作,比如调用connect()会发出SYN段*应用程序如何知

道TCP协议层的状态变化,比如从某个阻塞的socket函数返回就表明TCP协议收到了某些段,再比如read()返回0就表明收到了FIN段

12 TCP服务器客户端案例说明

server.c

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <stdio.h>

#include <string.h>

#include <netinet/in.h>

#include <ctype.h>

#include <unistd.h>

 

#define SERVER_PORT 8000

#define MAXLINE 4096

 

int main(void)

{

   
struct sockaddr_in serveraddr,clientaddr;

   
int sockfd,addrlen,confd,len,i;

   
//存储ip地址

   
char ipstr[128];

   
char buf[MAXLINE];

   

   
//1.socket

   
//AF_INET:表示使用的是Ipv4协议,如果想使用ipv6,使用AF_INET6

   
//SOCK_STREAM:表示使用的是TCP协议

   
sockfd = socket(AF_INET,SOCK_STREAM,0);

   
//2.bind,bzero将内容清零

   
bzero(&serveraddr,sizeof(serveraddr));

   
/* 地址族协议IPv4 */

   
serveraddr.sin_family = AF_INET;

   
/* IP地址 */

   
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

   
/*端口号*/

   
serveraddr.sin_port = htons(SERVER_PORT);

   
bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));

   
//3.listen,表示最大等待排队的数量为128个

   
listen(sockfd,128);

   
while(1) {

       
//4.accept 阻塞监听客户端链接请求

       
addrlen = sizeof(clientaddr);

       
confd = accept(sockfd,(struct sockaddr *)&clientaddr,&addrlen);

       
//输出客户端IP地址和端口号

       
inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr));

       
//打印除ip地址和端口号

       
printf("client ip %s\tport %d\n",

           
inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr)),

           
ntohs(clientaddr.sin_port));

 

       
//和客户端交互数据操作confd

       
//5.处理客户端请求,read,write默认是阻塞的。

       
len = read(confd,buf,sizeof(buf));

       
i = 0;

       
while(i < len) {

           
buf[i] = toupper(buf[i]);

      
     i++;

       
}

       
write(confd,buf,len);

       
//发生里4次链接

       
close(confd);

   
}

   
close(sockfd);

 

   
return 0;

}

client.c

#include <netinet/in.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <string.h>

#include <stdlib.h>

#include <sys/stat.h>

#include <unistd.h>

#include <fcntl.h>

 

#define SERVER_PORT 8000

#define MAXLINE 4096

 

int main(int argc,char *argv[])

{

   
struct sockaddr_in serveraddr;

   
int confd,len;

   
char ipstr[] = "192.168.6.14";

   
char buf[MAXLINE];

   
if(argc < 2) {

       
printf("./client str\n");

       
exit(1);

   
}

   
//1、创建一个socket

   
confd = socket(AF_INET,SOCK_STREAM,0);

   
//2、初始化服务器地址

   
bzero(&serveraddr,sizeof(serveraddr));

   
serveraddr.sin_family = AF_INET;

   
//"192.168.6.14"

   
inet_pton(AF_INET,ipstr,&serveraddr.sin_addr.s_addr);

   
serveraddr.sin_port = htons(SERVER_PORT);

   
//3.链接服务器处理数据

   
connect(confd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));

   
//4.请求服务器处理数据

   
write(confd,argv[1],strlen(argv[1]));

   
len = read(confd,buf,sizeof(buf));

   
write(STDOUT_FILENO,buf,len);

 

   
//关闭socket

   
close(confd);

   
return 0;

}

Makefile

all:server client

 

server:server.c

        
gcc $< -o $@

client:client.c

        
gcc $< -o $@

 

.PHONY:clean

clean:

        
rm -f server

        
rm -f client

运行:

在终端上输入make,先启动server端,在启动client,在启动客户端的时候同时输入字符串。

客户端运行效果:

时间: 2024-12-03 11:09:02

1.socket编程:socket编程,网络字节序,函数介绍,IP地址转换函数,sockaddr数据结构,网络套接字函数,socket相关函数,TCP server和client的相关文章

【linux网络编程】网络字节序、地址转换

网络字节序 故事的起源 "endian"这个词出自<格列佛游记>.小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位. 我们一般将"endian"翻译成"字节序",将 Big-Endian 和 Little-Endian 称作"大端格式"和"小端格式". 字节序 字节序是指多字节

网络字节序与主机字节序 高低位

最近在项目开发过程中,需要在采用JAVA作为语言的服务器与采用C++作为语言的服务器间进行通信,这就涉及到这两种语言间数据类型的转换以及网络字节序与主机字节序的区别.该文主要说说网络字节序和主机字节序的区别以及Little endian与Big endian的概念.其实编程的事就比较简单了   我也懒得写了,直接引用了我觉得写的挺好的两篇文章: 什么是Big Endian和Little Endian? 来源:http://blog.ednchina.com/qinyonglyz/194674/m

基于大端法、小端法以及网络字节序的深入理解_C 语言

关于字节序(大端法.小端法)的定义<UNXI网络编程>定义:术语"小端"和"大端"表示多字节值的哪一端(小端或大端)存储在该值的起始地址.小端存在起始地址,即是小端字节序:大端存在起始地址,即是大端字节序. 也可以说: 1.小端法(Little-Endian)就是低位字节排放在内存的低地址端即该值的起始地址,高位字节排放在内存的高地址端. 2.大端法(Big-Endian)就是高位字节排放在内存的低地址端即该值的起始地址,低位字节排放在内存的高地址端.举

c# 主机和网络字节序的转换 关于网络字节序和主机字节序的转换

最近使用C#进行网络开发,需要处理ISO8583报文,由于其中有些域是数值型的,于是在传输的时候涉及到了字节序的转换. 字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有两种字节顺序,根据他们所处的位置我们分别称为主机节序和网络字节序. 通常我们认为网络字节序为标准顺序,封包的时候,将主机字节序转换为网络字节序,拆包的时候要将网络字节序转换为主机字节序. 原以为还要自己写函数,其实网络库已经提供了. 主机到网络:short/int/long IPAddress.HostToNet

网络通信时字节序转换原理与网络字节序、大端和小端模式

引言:在进行网络通信时是否需要进行字节序转换?  相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换. 原因如下:网络协议规定接收到得第一个字节是高字节,存放到低地址,所以发送时会首先去低地址取数据的高字节.小端模式的多字节数据在存放时,低地址存放的是低字节,而被发送方网络协议函数发送时会首先去低地址取数据(想要取高字节,真正取得是低字节),接收方网络协议函数接收时会将接收到的第一个字节存放到低地址(想要接收高字节,真正接收的是低字节),所以最后

网络通信之 字节序转换原理与网络字节序、大端和小端模式

原文地址:http://www.cnblogs.com/fuchongjundream/p/3914770.html 一.在进行网络通信时是否需要进行字节序转换?       相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换.      原因如下:网络协议规定接收到得第一个字节是高字节,存放到低地址,所以发送时会首先去低地址取数据的高字节.小端模式的多字节数据在存放时,低地址存放的是低字节,而被发送方网络协议函数发送时会首先去低地址取数据(想要

Linux Socket学习--地址转换函数

 一个IP地址是由小数点分开的十进制数表示的,我们称之为点分十进制表示法.其中每一个十进制数代表一个字节的无符号数值(按照网络字节序)因为每个字节都是无符号的8位数值,这就限制了每一个字节所能表示的范围是0~255. Internet地址分类      一个Internet地址是由网络地址和主机地址构成的.      我们知道IP地址由32位二进制构成,但是网络地址和主机地址之间的界限并不是固定的,而界限的确定取决于地址的分类,下表总结了IP地址分类的方法: 理解网络掩码:      网络掩码的

socket-java的Socket通信中如何获取android手机wifi的IP地址。

问题描述 java的Socket通信中如何获取android手机wifi的IP地址. # java的Socket通信中如何获取android手机wifi的IP地址???. 解决方案 这个可以直接用java中的获取IP方法 InetAddress addr = InetAddress.getLocalHost(); ip=addr.getHostAddress().toString;//获得本机IP address=addr.getHostName()toString;//获得本机名称

新手看招:避免网络 IP 地址被非法修改_网络冲浪

局域网中各工作站的TCP/IP参数被随意修改后,很容易造成IP地址的冲突,这会给管理工作带来不小的麻烦.那么,有没有办法保护好自己的网络,不让别人非法修改IP地址呢? 其实,很简单,你只要参照下面的步骤,就能轻松避免IP地址被非法修改的麻烦! 注册表设置法 首先,需要将桌面上的"网上邻居"图标隐藏起来,让其他人无法通过"网上邻居"属性窗口,进入到TCP/IP参数设置界面.依次展开注册表编辑窗口中的"HKEY_CURRENT_USER"."