疯狂Java讲义:使用Socket进行通信[2]

疯狂Java讲义:使用Socket进行通信[2],第1张

程序清单 codes/ / /Client java

public class Client

{

public static void main(String[] args)

throws IOException

{

Socket socket = new Socket( )

//将Socket对应的输入流包装成BufferedReader

BufferedReader br = new BufferedReader(

new InputStreamReader(socket getInputStream()))

//进行普通IO *** 作

String line = br readLine()

System out println( 来自服务器数据 + line)

//关闭输入流 socket

br close()

socket close()

}

}

上面程序中粗体字代码是使用ServerSocket和Socket建立网络连接的代码 斜体字代码是通过Socket获取输入流 输出流进行通信的代码 通过程序不难看出 一旦使用ServerSocket Socket建立网络连接之后 程序通过网络通信与普通IO并没有太大的区别

先运行上面程序中的Server类 将看到服务器一直处于等待状态 因为服务器使用了死循环来接受来自客户端的请求 再运行Client类 将可看到程序输出 来自服务器的数据 您好 您收到了服务器的新年祝福! 这表明客户端和服务器端通信成功

上面程序为了档旅突出通过ServerSocket和Socket建立连接 并通过底层IO流进行通信的主题 程序没有进行异常处理 也没有使用finally块来关闭资源

实际应用中 程序可能不想让执行网络连接 读取服务器数据的进程一直阻塞 而是希望当网络连接 读取 *** 作超过合理时间之后 系统自动认为该 *** 作失败 这个合理时间就是超时时长 Socket对象提供了一个setSoTimeout(int timeout)来设置超时时长 如下的代码片段所示

Socket s = new Socket( )

//设置 秒之后即认为超时

s setSoTimeout( )

当我们为Socket对象指定了超时时长之后 如果在使用Socket进行读 写 *** 作完成之前已经超出了该时间限制 那么这些方法就会抛行御凳出SocketTimeoutException异常 程序可以对该异常进行捕捉 并进行适当处理 如下代码所示

try

{

//使用Scanner来读取网络输入流中的数据

Scanner scan = new Scanner(s getInputStream())

//读取一行字符

String line = scan nextLine()

}

//捕捉SocketTimeoutException异常

catch(SocketTimeoutException ex)

{

//对异常进行处理

}

假设程序需要为Socket连接服务器时指定超时时长 即经过指定时间后 如果该Socket还未连接到远程服务器 则系统认为该Socket连接超时 但Socket的所有构造器里都没有提供指定超时时长的参数 所以程序应该先创建一个无连接的Socket 再调用Socket的connect()方法来连接远程服务器 而connect方法就可拆兄以接受一个超时时长参数 如下代码所示

//创建一个无连接的Socket

Socket s = new Socket()

//让该Socket连接到远程服务器 如果经过 秒还没有连接到 则认为连接超时

s connconnect(new InetAddress(host port) )

       返回目录 疯狂Java讲义

       编辑推荐

       Java程序性能优化 让你的Java程序更快 更稳定

       新手学Java 编程

       Java程序设计培训视频教程

lishixinzhi/Article/program/Java/hx/201311/27265

UDP Server程序\x0d\x0a1、编写UDP Server程序的步骤\x0d\x0a(1)使用渣厅虚socket()来建立一个UDP socket,第二个参数为SOCK_DGRAM。\x0d\x0a(2)初始化sockaddr_in结构的变量,并赋值。sockaddr_in结构定义:\x0d\x0astruct sockaddr_in {\x0d\x0auint8_t sin_len\x0d\x0asa_family_t sin_family\x0d\x0ain_port_t sin_port\x0d\x0astruct in_addr sin_addr\x0d\x0achar sin_zero[8]\x0d\x0a}\x0d\x0a这里使用“08”作为服务程序的端口,使用“INADDR_ANY”作为绑定的IP地址即任何主机上的地址。\x0d\x0a(3)使用bind()把上面的socket和定义的IP地址和端口绑定。这里检查bind()是否执行成功,如果有错误就退出。这样可以防止服务程序重复运伏圆行的问题。\x0d\x0a(4)进入无限循环如燃程序,使用recvfrom()进入等待状态,直到接收到客户程序发送的数据,就处理收到的数据,并向客户程序发送反馈。这里是直接把收到的数据发回给客户程序。\x0d\x0a\x0d\x0a2、udpserv.c程序内容:\x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a\x0d\x0a#define MAXLINE 80\x0d\x0a#define SERV_PORT 8888\x0d\x0a\x0d\x0avoid do_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen)\x0d\x0a{\x0d\x0aint n\x0d\x0asocklen_t len\x0d\x0achar mesg[MAXLINE]\x0d\x0a\x0d\x0afor()\x0d\x0a{\x0d\x0alen = clilen\x0d\x0a/* waiting for receive data */\x0d\x0an = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len)\x0d\x0a/* sent data back to client */\x0d\x0asendto(sockfd, mesg, n, 0, pcliaddr, len)\x0d\x0a}\x0d\x0a}\x0d\x0a\x0d\x0aint main(void)\x0d\x0a{\x0d\x0aint sockfd\x0d\x0astruct sockaddr_in servaddr, cliaddr\x0d\x0a\x0d\x0asockfd = socket(AF_INET, SOCK_DGRAM, 0)/* create a socket */\x0d\x0a\x0d\x0a/* init servaddr */\x0d\x0abzero(&servaddr, sizeof(servaddr))\x0d\x0aservaddr.sin_family = AF_INET\x0d\x0aservaddr.sin_addr.s_addr = htonl(INADDR_ANY)\x0d\x0aservaddr.sin_port = htons(SERV_PORT)\x0d\x0a\x0d\x0a/* bind address and port to socket */\x0d\x0aif(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)\x0d\x0a{\x0d\x0aperror("bind error")\x0d\x0aexit(1)\x0d\x0a}\x0d\x0a\x0d\x0ado_echo(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr))\x0d\x0a\x0d\x0areturn 0\x0d\x0a}\x0d\x0a\x0d\x0aUDP Client程序\x0d\x0a1、编写UDP Client程序的步骤\x0d\x0a(1)初始化sockaddr_in结构的变量,并赋值。这里使用“8888”作为连接的服务程序的端口,从命令行参数读取IP地址,并且判断IP地址是否符合要求。\x0d\x0a(2)使用socket()来建立一个UDP socket,第二个参数为SOCK_DGRAM。\x0d\x0a(3)使用connect()来建立与服务程序的连接。与TCP协议不同,UDP的connect()并没有与服务程序三次握手。上面我们说了UDP是非连接的,实际上也可以是连接的。使用连接的UDP,kernel可以直接返回错误信息给用户程序,从而避免由于没有接收到数据而导致调用recvfrom()一直等待下去,看上去好像客户程序没有反应一样。\x0d\x0a(4)向服务程序发送数据,因为使用连接的UDP,所以使用write()来替代sendto()。这里的数据直接从标准输入读取用户输入。\x0d\x0a(5)接收服务程序发回的数据,同样使用read()来替代recvfrom()。\x0d\x0a(6)处理接收到的数据,这里是直接输出到标准输出上。\x0d\x0a\x0d\x0a2、udpclient.c程序内容:\x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a\x0d\x0a#define MAXLINE 80\x0d\x0a#define SERV_PORT 8888\x0d\x0a\x0d\x0avoid do_cli(FILE *fp, int sockfd, struct sockaddr *pservaddr, socklen_t servlen)\x0d\x0a{\x0d\x0aint n\x0d\x0achar sendline[MAXLINE], recvline[MAXLINE + 1]\x0d\x0a\x0d\x0a/* connect to server */\x0d\x0aif(connect(sockfd, (struct sockaddr *)pservaddr, servlen) == -1)\x0d\x0a{\x0d\x0aperror("connect error")\x0d\x0aexit(1)\x0d\x0a}\x0d\x0a\x0d\x0awhile(fgets(sendline, MAXLINE, fp) != NULL)\x0d\x0a{\x0d\x0a/* read a line and send to server */\x0d\x0awrite(sockfd, sendline, strlen(sendline))\x0d\x0a/* receive data from server */\x0d\x0an = read(sockfd, recvline, MAXLINE)\x0d\x0aif(n == -1)\x0d\x0a{\x0d\x0aperror("read error")\x0d\x0aexit(1)\x0d\x0a}\x0d\x0arecvline[n] = 0/* terminate string */\x0d\x0afputs(recvline, stdout)\x0d\x0a}\x0d\x0a}\x0d\x0a\x0d\x0aint main(int argc, char **argv)\x0d\x0a{\x0d\x0aint sockfd\x0d\x0astruct sockaddr_in srvaddr\x0d\x0a\x0d\x0a/* check args */\x0d\x0aif(argc != 2)\x0d\x0a{\x0d\x0aprintf("usage: udpclient \n")\x0d\x0aexit(1)\x0d\x0a}\x0d\x0a\x0d\x0a/* init servaddr */\x0d\x0abzero(&servaddr, sizeof(servaddr))\x0d\x0aservaddr.sin_family = AF_INET\x0d\x0aservaddr.sin_port = htons(SERV_PORT)\x0d\x0aif(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) 回答于 2022-11-17


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12311195.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存