精华内容
下载资源
问答
  • TCP编程

    千次阅读 2018-06-29 15:00:21
    TCP编程的服务器端一般步骤是:  1、创建一个socket,用函数socket();  2、设置socket属性,用函数setsockopt(); * 可选  3、绑定IP地址、端口等信息到socket上,用函数bind();  4、开启监听,用函数listen...

    TCP

    TCP编程的服务器端一般步骤是:
      1、创建一个socket,用函数socket();
      2、设置socket属性,用函数setsockopt(); * 可选
      3、绑定IP地址、端口等信息到socket上,用函数bind();
      4、开启监听,用函数listen();
      5、接收客户端上来的连接,用函数accept();
      6、收发数据,用函数send()和recv(),或者read()和write();
      7、关闭网络连接;
      8、关闭监听;
     

    #!/usr/bin/env python3
    #-*- coding:utf8 -*-
    
    import socket
    import time
    import threading
    
    # 创建tcp socket, 面向流模式
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 绑定IP地址 端口号
    s.bind(('127.0.0.1', 5000))
    # 开启监听, 5为等待连接的最大数
    s.listen(5)
    print("Waiting for connection...")
    
    def tcplink(sock, addr):
        print("Accept new connection from {}:{}".format(addr[0], addr[1]))
        sock.send(b'Welcome')
        while True:
            data = sock.recv(1024)
            time.sleep(1)
            if not data or data.decode('utf-8') == 'exit':
                break
            sock.send('Hello, {}'.format(data.decode('utf-8')).encode('utf-8'))
        sock.close()
        print('Connection from {}:{} closed.'.format(addr[0], addr[1]))
    
    # 用循环来接受来自客户端的连接
    while True:
        # 接受一个新连接
        sock, addr = s.accept()
        # 创建线程来处理TCP连接
        t = threading.Thread(target=tcplink, args=(sock, addr))
        t.start()

    TCP编程的客户端一般步骤是:
      1、创建一个socket,用函数socket();
      2、连接服务器,用函数connect(),指定对方IP与端口;
      3、收发数据,用函数send()和recv(),或者read()和write();
      4、关闭网络连接;

    #!/usr/bin/env python3
    #-*- coding:utf8 -*-
    import socket
    
    # 创建socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 建立连接
    s.connect(('127.0.0.1', 5000))
    # 接收消息
    print(s.recv(1024).decode('utf-8'))
    for data in [b'Michael', b'Tracy', b'Sarah']:
        # 发送数据
        s.send(data)
        print(s.recv(1024).decode('utf-8'))
    s.send(b'exit')
    s.close()
    展开全文
  • Go TCP编程

    千次阅读 2020-06-01 23:05:46
    Go TCP编程 一、服务端编程步陬: 1.创建套接字 2.监听套接字 3.处理请求 server/tcp_server.go package server import ( "fmt" "net" "github.com/jstang007/gateway_demo/httpserver/handler" ) // SrvForever ...

    Go TCP编程
    一、服务端编程step:
    1.1 创建套接字
    1.2 监听套接字
    1.3 处理请求

    server/tcp_server.go

    package server
    import (
    	"fmt"
    	"net"
    	"github.com/jstang007/gateway_demo/httpserver/handler"
    )
    // SrvForever 服务端启动函数
    func SrvForever() {
    	//1、创建套接字
    	listenner, err := net.Listen("tcp", "0.0.0.0:9091")
    	if err != nil {
    		fmt.Printf("listen fail, err:%v\n", err)
    		return
    	}
    	//2、监听套接字
    	for {
    		conn, err := listenner.Accept() //接收请求, 阻塞态
    		if err != nil {
    			fmt.Printf("accept fail, err:%v\n", err)
    			continue
    		}
    		//3、处理请求
    		go handler.Process(conn)
    	}
    }
    

    二、客户端编程step
    2.1 创建套接字
    2.2 发送消息

    package client
    import (
    	"fmt"
    	"net"
    	"github.com/jstang007/gateway_demo/httpserver/handler"
    )
    //TCPClient 客户端
    func TCPClient() {
    	conn, err := net.Dial("tcp", "localhost:9091") //创建套接字
    	if err != nil {
    		fmt.Printf("connect failed, error:%v", err)
    	}
    	defer conn.Close()
    	handler.Send(conn, "my name is TCP Client!")
    }
    

    三、消息处理函数
    3.1 消息解码
    3.2 消息编码
    3.3 发送消息
    3.4 接收处理消息
    handler/base_handler.go

    package handler
    import (
    	"encoding/binary"
    	"fmt"
    	"io"
    	"net"
    )
    //MsgHeader 消息头
    var MsgHeader = "12345678"
    
    // decode 解码,将字节流解码成utf-8
    func decode(bytesBuffer io.Reader) (bodyBuf []byte, err error) {
    	//1.首先读取消息头数据存到MagicBuf
    	MagicBuf := make([]byte, len(MsgHeader))
    	if _, err = io.ReadFull(bytesBuffer, MagicBuf); err != nil {
    		return nil, err
    	}
    
    	//2、读取消息内容长度到lengthBuf
    	lengthBuf := make([]byte, 4)
    	if _, err := io.ReadFull(bytesBuffer, lengthBuf); err != nil {
    		return nil, err
    	}
    
    	//3.读取消息内容到bodyBuf
    	length := binary.BigEndian.Uint32(lengthBuf)
    	bodyBuf = make([]byte, length)
    	if _, err := io.ReadFull(bytesBuffer, bodyBuf); err != nil {
    		return nil, err
    	}
    	return bodyBuf, err
    }
    
    // Process 处理请求
    func Process(conn net.Conn) {
    	defer conn.Close()
    	for {
    		bt, err := decode(conn)
    		if err != nil {
    			fmt.Printf("read from connect failed, err:%v\n", err)
    			break
    		}
    		str := string(bt)
    		fmt.Printf("receive from client, data: %s\n", str)
    	}
    }
    
    // Send 发送消息
    func Send(conn net.Conn, content string) error {
    	return encode(conn, content)
    }
    
    // encode 将string字符串转换成字节流
    func encode(bytesBuffer io.Writer, contetnt string) error {
    	//1.写入消息头
    	bytesMsgHeader := []byte(MsgHeader)
    	if err := binary.Write(bytesBuffer, binary.BigEndian, bytesMsgHeader); err != nil {
    		return err
    	}
    	//2.写入内容长度
    	clen := int32(len([]byte(contetnt)))
    	if err := binary.Write(bytesBuffer, binary.BigEndian, clen); err != nil {
    		return err
    	}
    	//3.写入内容
    	bytesContent := []byte(contetnt)
    	if err := binary.Write(bytesBuffer, binary.BigEndian, bytesContent); err != nil {
    		return err
    	}
    	return nil
    }
    

    四、测试函数
    test/main.go

    package main
    import (
    	"fmt"
    	"time"
    	"github.com/jstang007/gateway_demo/httpserver/client"
    	"github.com/jstang007/gateway_demo/httpserver/server"
    )
    func main() {
    	//启动服务器
    	go server.SrvForever()
    	//启动客户端
    	for i := 0; i < 5; i++ {
    		time.Sleep(time.Second * 2)
    		fmt.Printf("-------启动客户端[%v]--------\n", i)
    		client.TCPClient()
    	}
    }
    

    在这里插入图片描述
    EOF表示读完数据了

    展开全文
  • Linux 网络编程——TCP编程

    万次阅读 多人点赞 2015-05-12 12:33:55
    TCP 具有以下特点:1)电话系统服务模式的抽象2)每一次完整的数据传输都要经过建立连接、使用连接、终止连接的过程3)可靠、出错重传、且每收到一个数据都要给出相应的确认,保证数据传输的可靠性TCP 编程的 C/S ...

    概述

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。


    TCP 具有以下特点:

    1)电话系统服务模式的抽象

    2)每一次完整的数据传输都要经过建立连接、使用连接、终止连接的过程

    3)可靠、出错重传、且每收到一个数据都要给出相应的确认,保证数据传输的可靠性


    TCP 编程的 C/S 架构

    基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下:

    TCP 客户端编程


    对于 TCP 客户端编程流程,有点类似于打电话过程:找个可以通话的手机(socket() ) -> 拨通对方号码并确定对方是自己要找的人( connect() ) -> 主动聊天( send() 或 write() )-> 或者,接收对方的回话( recv() 或 read() )-> 通信结束后,双方说再见挂电话(close() )。


    所需头文件:#include <sys/socket.h>

    int socket(int family,int type,int protocol);
    功能:
    创建一个用于网络通信的 socket套接字(描述符),详细用法,请看《套接字的介绍》
    参数:
    family:本示例写 AF_INET,代表 IPv4
    type:本示例写 SOCK_STREAM,代表 TCP 数据流
    protocol:这里写 0,设为 0 表示使用默认协议
    返回值:
    成功:套接字
    失败 < 0 

    int connect( int sockfd, const struct sockaddr *addr, socklen_t len );

    功能:

    主动跟服务器建立连接,有点类似于,我们给别人电话,主动拨对方的电话号码,具体是怎么一个过程,请《connect()、listen()和accept()三者之间的关系》

    参数:

    sockfdsocket()返回的套接字

    addr:连接的服务器地址结构

    len:地址结构体长度

    返回值:

    成功:0    

    失败:-1


    connect() 函数相当于拨号码,只有拨通号码并且确定对方是自己要找的人(三次握手才能进行下一步的通信


    ssize_t send(int sockfd, const void* buf, size_t nbytes, int flags);

    功能:

    发送数据,最后一个参数为 0 时,可以用 write() 替代( send 等同于 write )。注意:不能用 TCP 协议发送 0 长度的数据包。假如,数据没有发送成功,内核会自动重发。

    参数:

    sockfd: 已建立连接的套接字

    buf 发送数据的地址

    nbytes: 发送缓数据的大小(以字节为单位)

    flags 套接字标志(常为 0)

    返回值:

    成功:成功发送的字节数

    失败 < 0


    这里通过 Windows 的网络调试助手和虚拟机中的 ubuntu 客户端程序进行通信,网络调试助手下载请点此处


    Windows 的网络调试助手作为 TCP 服务器,接收客户端的请求,调试助手配置如下:



    虚拟机中 ubuntu 的 TCP 客户端程序代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    int main(int argc, char *argv[])
    {
    	unsigned short port = 8080;        		// 服务器的端口号
    	char *server_ip = "10.221.20.10";    	// 服务器ip地址
    	
    	if( argc > 1 )		//函数传参,可以更改服务器的ip地址									
    	{		
    		server_ip = argv[1];
    	}	
    	if( argc > 2 )	   //函数传参,可以更改服务器的端口号									
    	{
    		port = atoi(argv[2]);
    	}
    
    	int sockfd;
    	sockfd = socket(AF_INET, SOCK_STREAM, 0);// 创建通信端点:套接字
    	if(sockfd < 0)
    	{
    		perror("socket");
    		exit(-1);
    	}
    	
    	// 设置服务器地址结构体
    	struct sockaddr_in server_addr;
    	bzero(&server_addr,sizeof(server_addr)); // 初始化服务器地址
    	server_addr.sin_family = AF_INET;	// IPv4
    	server_addr.sin_port = htons(port);	// 端口
    	inet_pton(AF_INET, server_ip, &server_addr.sin_addr);	// ip
    	
    	 // 主动连接服务器
    	int err_log = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));     
    	if(err_log != 0)
    	{
    		perror("connect");
    		close(sockfd);
    		exit(-1);
    	}
    	
    	char send_buf[512] = {0};
    	printf("send data to %s:%d\n",server_ip,port);
    	while(1)
    	{
    		printf("send:");
    		fgets(send_buf,sizeof(send_buf),stdin); // 输入内容
    		send_buf[strlen(send_buf)-1]='\0';
    		send(sockfd, send_buf, strlen(send_buf), 0);   // 向服务器发送信息
    	}
    
    	close(sockfd);
    	
    	return 0;
    }
    

    运行结果如下:



    对于客户端,也是可以接收数据,前提为,客户端先给服务器发送数据。

    ssize_t recv(int sockfd, void *buf,  size_t nbytes, int flags);

    功能:

    接收网络数据,默认的情况下,如果没有接收到数据,这个函数会阻塞,直到有数据到来。

    参数:

    sockfd套接字

    buf接收网络数据的缓冲区的地址

    nbytes:接收缓冲区的大小(以字节为单位)

    flags套接字标志(常为 0 )

    返回值:

    成功:成功接收的字节数

    失败 < 0


    测试代码如下:

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    int main(int argc, char *argv[])
    {
    	unsigned short port = 8080;        		// 服务器的端口号
    	char *server_ip = "10.221.20.10";    	// 服务器ip地址
    	
    	if( argc > 1 )		//函数传参,可以更改服务器的ip地址									
    	{		
    		server_ip = argv[1];
    	}	
    	if( argc > 2 )	   //函数传参,可以更改服务器的端口号									
    	{
    		port = atoi(argv[2]);
    	}
    
    	int sockfd;
    	sockfd = socket(AF_INET, SOCK_STREAM, 0);// 创建通信端点:套接字
    	if(sockfd < 0)
    	{
    		perror("socket");
    		exit(-1);
    	}
    	
    	// 设置服务器地址结构体
    	struct sockaddr_in server_addr;
    	bzero(&server_addr,sizeof(server_addr)); // 初始化服务器地址
    	server_addr.sin_family = AF_INET;	// IPv4
    	server_addr.sin_port = htons(port);	// 端口
    	inet_pton(AF_INET, server_ip, &server_addr.sin_addr);	// ip
    	
    	 // 主动连接服务器
    	int err_log = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));     
    	if(err_log != 0)
    	{
    		perror("connect");
    		close(sockfd);
    		exit(-1);
    	}
    	
    	
    	printf("send data to %s:%d\n",server_ip,port);
    	
    	char send_buf[512] = "Hi, I am Mike.";
    	send(sockfd, send_buf, strlen(send_buf), 0);   // 向服务器发送信息
    	
    	char recv_buf[512] = {0};
    	recv(sockfd, recv_buf, sizeof(send_buf), 0); // 接收数据
    	printf("recv_buf ========== %s\n", recv_buf);
    
    	close(sockfd);
    	
    	return 0;
    }


    运行结果如下:



    TCP 服务器编程

    做为 TCP 服务器需要具备的条件呢?

    • 具备一个可以确知的地址( bind() ):相当于我们要明确知道移动客服的号码,才能给他们电话;
    • 让操作系统知道是一个服务器,而不是客户端( listen() ):相当于移动的客服,他们主要的职责是被动接听用户电话,而不是主动打电话骚扰用户;
    • 等待连接的到来( accept() ):移动客服时刻等待着,来一个客户接听一个。

    接收端使用 bind() 函数,来完成地址结构与socket 套接字的绑定,这样 ip、port 就固定了,发送端即可发送数据给有明确地址( ip+port ) 的接收端。


    对于 TCP 服务器编程流程,有点类似于接电话过程:找个可以通话的手机(socket() ) -> 插上电话卡固定一个号码( bind() ) -> 职责为被动接听,给手机设置一个铃声来监听是否有来电( listen() ) -> 有来电,确定双方的关系后,才真正接通不挂电话( accept() ) -> 接听对方的诉说( recv() ) -> 适当给些回话( send() )-> 通信结束后,双方说再见挂电话( close() )。


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

    功能:

    将本地协议地址与 sockfd 绑定,这样 ip、port 就固定了

    参数:

    sockfdsocket 套接字

    myaddr: 指向特定协议的地址结构指针

    addrlen:该地址结构的长度

    返回值:

    成功:返回 0

    失败:-1


    使用实例如下:

    // 本地网络地址
    struct sockaddr_in my_addr;
    bzero(&my_addr, sizeof(my_addr));	// 清空结构体内容
    my_addr.sin_family = AF_INET;	// ipv4
    my_addr.sin_port   = htons(port);	// 端口转换
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定网卡所有ip地址,INADDR_ANY为通配地址,值为0
    
    printf("Binding server to port %d\n", port);
    int err_log;
    err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr)); // 绑定
    if(err_log != 0)
    {
    	perror("bind");
    	close(sockfd);		
    	exit(-1);
    }

    int listen(int sockfd, int backlog);

    功能:

    将套接字由主动修改为被动,使操作系统为该套接字设置一个连接队列,用来记录所有连接到该套接字的连接。更详细说明,请看《connect()、listen()和accept()三者的关系》

    参数:

    sockfd: socket监听套接字

    backlog:连接队列的长度

    返回值:

    成功:返回0

    失败:其他


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

    功能:

    从已连接队列中取出一个已经建立的连接,如果没有任何连接可用,则进入睡眠等待(阻塞)。更详细说明,请看《connect()、listen()和accept()三者的关系》

    参数:

    sockfd: socket监听套接字

    cliaddr: 用于存放客户端套接字地址结构

    addrlen:套接字地址结构体长度的地址

    返回值:

    成功:已连接套接字。注意:返回的是一个已连接套接字,这个套接字代表当前这个连接

    失败:< 0


    ubuntu 中的服务器代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>						
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>				
    int main(int argc, char *argv[])
    {
    	unsigned short port = 8080;	// 本地端口	
    	if(argc > 1)						
    	{
    		port = atoi(argv[1]);
    	}
    	
    	int sockfd = socket(AF_INET, SOCK_STREAM, 0);   // 创建通信端点:套接字
    	if(sockfd < 0)
    	{
    		perror("socket");
    		exit(-1);
    	}
    	
    	// 设置本地地址结构体
    	struct sockaddr_in my_addr;
    	bzero(&my_addr, sizeof(my_addr));	// 清空    
    	my_addr.sin_family = AF_INET;	// ipv4
    	my_addr.sin_port   = htons(port);	// 端口
    	my_addr.sin_addr.s_addr = htonl(INADDR_ANY);	// ip
    	
    	// 绑定
    	int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
    	if( err_log != 0)
    	{
    		perror("binding");
    		close(sockfd);		
    		exit(-1);
    	}
    	
    	err_log = listen(sockfd, 10); // 监听,监听套接字改为被动
    	if(err_log != 0)
    	{
    		perror("listen");
    		close(sockfd);		
    		exit(-1);
    	}	
    	
    	printf("listen client @port=%d...\n",port);
    
    	while(1)
    	{	
    	
    		struct sockaddr_in client_addr;		   
    		char cli_ip[INET_ADDRSTRLEN] = "";	   
    		socklen_t cliaddr_len = sizeof(client_addr);    
    		
    		int connfd;
    		// 等待连接
    		connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);       
    		if(connfd < 0)
    		{
    			perror("accept");
    			continue;
    		}
    
    		inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);
    		printf("----------------------------------------------\n");
    		printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));
    		
    		char recv_buf[512] = "";
    		while( recv(connfd, recv_buf, sizeof(recv_buf), 0) > 0 ) // 接收数据
    		{
    			printf("\nrecv data:\n");
    			printf("%s\n",recv_buf);
    		}
    		
    		close(connfd);     //关闭已连接套接字
    		printf("client closed!\n");
    	}
    	
    	close(sockfd);         //关闭监听套接字
    	
    	return 0;
    }


    Windows 的网络调试助手作为 TCP 客户端,给 ubuntu 中的服务器发送数据,运行结果如下:



    关闭连接:close()

    使用 close() 函数即可关闭套接字,关闭一个代表已连接套接字将导致另一端接收到一个 0 长度的数据包,详情请看《 TCP 四次挥手》


    做服务器时

    • 关闭监听套接字( socket()和listen()之后的套接字 )将导致服务器无法接收新的连接,但不会影响已经建立的连接;
    • 关闭 accept()返回的已连接套接字将导致它所代表的连接被关闭,但不会影响服务器的监听( socket()和listen()之后的套接字 )。


    做客户端时

    关闭连接就是关闭连接,不意味着其他。


    如果客户端和服务器已经连接成功的前提下,通常的情况下,先关闭客户端,再关闭服务器,如果是先关闭服务器,立马启动服务器是,服务器绑定的端口不会立马释放(如下图),要过 1 分钟左右才会释放,为什么会这样的呢?请看《 TCP 四次挥手》。有没有方法让服务器每次启动都能立即成功?请看《端口复用》



    本教程示例代码下载请点此处。



    展开全文
  • java TCP编程

    千次阅读 多人点赞 2019-01-04 17:13:55
    TCP编程基于 请求—响应 在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序 第一次通讯中等待连接的程序被称作服务器端(Server)程序 利用IO流实现数据的传输 单向 :只有请求 双向:请求—响应 循环...

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    * 需求:完成网络登录功能:

    • 用户输入用户名密码,服务器给出登录成功或失败的提示
      • TCP编程基于 请求—响应
      • 在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序
      • 第一次通讯中等待连接的程序被称作服务器端(Server)程序
      • 利用IO流实现数据的传输
      • 单向 :只有请求
      • 双向:请求—响应
      • 循环双向:持续(请求—响应)

    客户端Socket

    • 此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。 客户端的步骤
      1:创建客户端的套接字
      2:获取输出流
      3:输出流写数据
      4:关闭套接字
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class ClientDemo {
    		public static void main(String[] args) throws IOException {
    		//1:创建客户端的套接字  做连接  指定服务器的ip+端口
    		Socket s = new Socket("192.168.3.135", 10086);
    		//2:获取输出流
    		OutputStream os = s.getOutputStream();
    		//3:写数据
    		os.write(97);
    		os.write(98);
    		os.write(99);
    		//4:关闭套接字
    		s.close();
    		
    		
    	}
    
    }
    

    服务器端ServerSocket

    • 此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
      服务器的步骤
      1:创建服务器的套接字
      2:监听客户端的套接字
      3:获取输入流读取内容
      4:关闭套接字
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class ServerDemo {
    
    	public static void main(String[] args) throws IOException {
    		//1:创建服务器的套接字
    		ServerSocket ss = new ServerSocket(10086);
    		//2:监听客户端的套接字,并且返回客户端的套接字
    		Socket s = ss.accept();  //阻塞式方法
    		//3:获取输入流
    		InputStream is = s.getInputStream();
    		//4:读取数据
    		byte[] by = new byte[1024];
    		int num = 0;
    		while((num = is.read())!=-1){
    			System.out.print((char)num);
    		}
    		//5:关闭套接字
    		s.close();
    		
    		
    	}
    
    }
    

    优化后

    • 客户端通过键盘录入用户名和密码,发送给服务器
      * 注意:一次请求对应一次响应
      * 如果多次请求,必须重新建立连接,建立新的scoket

    Client

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class ClientDemo {
    	public static void main(String[] args) throws IOException {
    		//1:创建客户端的套接字
    		Socket s = new Socket("localhost", 10086);
    		//2:获取输出流 
    		//第1层:字符缓冲输出流
    		//第2层:字符转换输出流
    		//第3层:字节输出流
    		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
    		//3 获取输入流
    		BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
    		Scanner sc = new Scanner(System.in);
    		System.out.println("请输入用户名");
    		 String userName = sc.nextLine();
    		System.out.println("请输入密码");
    		String password = sc.nextLine();
    		//3:写数据
    		bw.write(userName);
    		bw.newLine();
    		bw.write(password);
    		bw.flush();
    		//bw.close();  //切记,缓冲流写数据,需要刷空!!!
    		
    		//告诉服务器。客户端这边数据写入完毕
    		s.shutdownOutput();
    		
    		//4:读取从服务器响应的数据
    		String info = br.readLine(); //阻塞式方式
    		System.out.println(info);
    		
    		//4:关闭套接字
    		s.close();
    		
    		
    	}
    
    }
    
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    public class ServerDemo {
    	
    	public static Map<String, String> getUserInfo() throws FileNotFoundException, IOException{
    		
    		Properties p = new Properties();
    		p.load(new FileInputStream("user.properties"));
    		String userName = p.getProperty("userName");
    		String password = p.getProperty("password");
    		
    		Map<String, String> map = new HashMap<>();
    		map.put("userName", userName);
    		map.put("password", password);
    		
    		return map;
    		
    	}
    	   
    
    	public static void main(String[] args) throws IOException {
    		
    		//1:创建服务器端套接字
    		ServerSocket ss = new ServerSocket(10086);
    		//2:监听客户端的套接字
    		Socket s = ss.accept();
    		//3:获取输入流
    		//第1层:字符缓冲输入流
    		//第2层:字符转换输入流
    		//第3层:字节输入流
    		BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
    		//4:获取输出流
    		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
    		//4:读取数据
    		String userName = br.readLine();
    		String password = br.readLine();
    		//5:判断用户名和密码
    		//获取正确的用户名和密码
    		Map<String, String> map = getUserInfo();
    		
    		System.out.println(userName);
    		System.out.println("--------------------------");
    		
    		if(map.get("userName").equals(userName)&&map.get("password").equals(password)){
    			//需要将响应返回给客户端
    			//System.out.println("登陆成功");
    			bw.write("登陆成功");
    			bw.flush();
    		}else{
    			bw.write("登陆失败");
    			bw.flush();
    		}
    		
    		
    		//5:关闭客户端套接字
    	         s.close();
    	}
    }
    
    

    upload

    • 需求:客户端上传文件给服务器

    • 源地址:D://工具//
      目的地:当前项目
      客户端步骤
      1:创建一个输入流读取D://工具/某一个文件,读取到程序中
      2:创建客户端的套接字
      3:通过客户端的套接字获取输出流
      4:将程序中的文件通过输出流写入到服务器
      5:关闭套接字

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.Socket;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    public class Client {
    	
    	/**
    	 * 遍历需要上传的文件
    	 */
    	public static String dirFile(){
    		Scanner sc = new Scanner(System.in);
    		//创建Map集合保存文件的编号以及文件的路径
    		Map<String, String> map = new HashMap<>(); 
    		System.out.println("---客户端上传文件---");
    		System.out.println("请选择要上传的文件编号:");
    		//1:创建一个File文件
    		File file = new File("D:/工具");
    		//2:遍历File的目录
    		File[] listFiles = file.listFiles();
    		int count = 1;
    		for (File file2 : listFiles) {
    			if(file2.isFile()){
    				System.out.println((count)+":"+file2.getAbsolutePath());
    				//保存编号和文件名
    				map.put(String.valueOf(count), file2.getAbsolutePath());
    				count++;
    			}
    		}
    		//录入文件的编号
    		String num = sc.nextLine();
    		//通过录入的编号取集合中找文件的路径
    		String path = map.get(num);
    		//返回文件路径
    		return path;
    	}
    	public static void upload() throws IOException{
    		//1:获取文件的路径
    		String path = dirFile();
    		//2:创建字节缓冲输入流
    		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
    		//3:创建客户端的套接字
    		Socket s = new Socket("127.0.0.1", 10086);
    		//4:通过套接字获取输出流
    		BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
    		//5:一边读取,一边写入
    		byte [] by = new byte[1024];
    		int num = 0;
    		while((num=bis.read(by))!=-1){
    			//把文件写入服务器
    			bos.write(by, 0, num);
    		}
    		//通知服务器客户端写入完毕
    		s.shutdownOutput();
    		//获取一个输入流
    		BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
    		String info = br.readLine();
    		System.out.println(info);
    		
    		//6:关闭流和套接字
    		bis.close();
    		s.close();
    	}
    	
    	
    	public static void main(String[] args) {
    		try {
    			upload();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    }
    
    
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.BufferedWriter;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.UUID;
    
    public class Server {
    	
    	/*
    	 * 服务器接受客户端上传的文件
    	 *  保存地址:当先项目下的file文件下
    	 * 
    	 */
    	public static void main(String[] args) throws IOException {
    		//1创建服务器端的套接字
    		ServerSocket ss = new ServerSocket(10086);
    		System.out.println("等待文件上传...");
    		//2:监听客户端的套接字,并且获取套接字
    		Socket s = ss.accept();
    		//3:通过客户端的套接字获取一个输入流
    		BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
    		//4:创建一个输出流
    		UUID uuid = UUID.randomUUID();
    		System.out.println(uuid);
    		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("file//"+uuid.toString()+".zip"));
    		//4:读取流中内容
    		byte[] by = new byte[1024];
    		int num = 0;
    		while((num=bis.read(by))!=-1){
    			bos.write(by, 0, num);
    		}
    		System.out.println("---------------");
    		//给客户端一个响应 :上传成功
    		//获取一个输出流
    		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())) ;
    		bw.write("上传成功");
    		bw.flush();
    		//5:关闭流
    		//bos.close();
    		s.close();
    		
    	}
    
    }
    
    
    展开全文
  • Day23一、网络编程1、网络编程的概念2、IP地址和端口号二、UDP协议和TCP协议1、通信协议2、UDP协议和TCP协议三、UDP编程和TCP编程1、InetAddress类2、Socket编程3、UDP编程说明4、TCP编程 一、网络编程 1、网络编程...
  • linux下tcp编程

    千次阅读 2019-06-03 16:27:58
    今天比较闲,玩一下linux下的TCP编程,下面是具体实现以及对TCP编程的具体总结。 服务端实现: #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<stdio.h> #...
  • 一种udp 不关心数据是否会丢失,在乎传输效率TCP编程 一点:服务端 二点:客户端客户端如何连接服务端,保证传输的数据可靠呢? 第一次握手:客户端发送报文,连接服务端 第二次握手:服务端发送报文,你可以...
  • VC++之网络编程三 TCP编程实例

    千次阅读 2014-07-12 20:48:46
    TCP编程实例
  • GO语言使用之网络编程(TCP编程)

    千次阅读 2018-09-13 09:24:02
    网络编程是一个复杂的学科, 协议(TCP/IP)、IP地址、端口等,推荐学习TCP-IP协议卷1-3. 下面通过一个实例来感受go中的TCP 编程。 二、TCP快速入门案例 1、服务端 服务端的处理流程: 监听端口 8888 接收...
  • Java中的TCP编程

    千次阅读 2019-01-04 21:01:05
    TCP编程基于 请求—响应 在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序 第一次通讯中等待连接的程序被称作服务器端(Server)程序 利用IO流实现数据的传输 单向 :只有请求 双向:请求—响应 循环...
  • TCP编程流程

    千次阅读 2019-06-09 18:59:02
    TCP是传输控制协议的简称,是TCP/IP体系中的面向连接的传输层协议,在网络中提供全双工的、可靠的服务。在上一章节中可知,TCP通信是通过套接字通信机制...图8.1 使用TCP时套接字编程流程 socket编程的基本函数有s...
  • Python TCP编程

    2018-08-28 16:49:00
    TCP Socket Python中使用Socket编程 服务端 客户端 TCP 对于TCP,我想大部分同学不会陌生。TCP是一个网络层协议,通过TCP可以建立客户端到服务器的连接,并相互传递数据。那么在python中如何使用TCP...
  • TCP编程步骤概述

    千次阅读 2015-09-09 01:38:14
    TCP编程的服务器端一般步骤是: 1、创建一个socket,用函数socket(); 2、准备通信地址 3、绑定IP地址、端口等信息到socket上,用函数bind(); 4、开启监听,用函数listen(); 5、接收客户端上来的连接,用函数...
  • TCP编程模型服务器端调用序列:1.调用socket函数创建套接字;2.调用bind函数绑定本地地址和端口号;3.调用listen启动监听;4.调用accept从已连接队列中提取客户连接;5.调用IO函数(read/write)与客户端通信;6....
  • MFC中socket TCP编程问题

    2015-06-01 12:42:11
    我在控制台用socket的tcp编程,测试完全没有问题。但是把它直接用在MFC对话框的一个按钮中,先点击服务器端的按钮,再点击客户端的按钮后,服务器端就死机了,一直就是未响应。。求救\("▔□▔)/谢谢!
  • python中的TCP编程学习

    千次阅读 2015-07-18 15:30:13
    今天看了一下关于python的TCP编程。发现思路和其他语言(例如java)思路基本上差不多。先看客户端。基本步骤如下: 第一步:创建一个socket 第二步:建立连接 第三步:发送数据 第四步:读取从服务器发送过来...
  • Erlang TCP编程Demo

    2011-09-03 14:32:43
    今天学习了一下Erlang TCP编程,做了一个小Demo. 感觉比较好用的功能是:每当客户端Socket关闭的时候,会向服务器发送一条{error, closed}的消息,反之亦然。好像Java没有这个功能。 [code="erlang"] -module...
  • 基于Linux下的TCP编程

    万次阅读 多人点赞 2011-09-14 18:27:31
    基于Linux的TCP网络编程一.Linux下TCP编程框架TCP网络编程的流程包含服务器和客户端两种模式。服务器模式创建一个服务程序,等待客户端用户的连接,接收到用户的连接请求后,根据用户的请求进行处理;客户端模式则...
  • C#Socket教程详解一:同步TCP编程

    千次阅读 2018-07-18 15:06:13
    异步TCP编程传送门:https://blog.csdn.net/shazhiwutx/article/details/81134174 服务端重要类: TcpListener类,服务器监听类,用于监听和连接客户端,该类重要方法如下:   构造方法: public TcpListener...
  • Tcp编程下的多线程任务

    千次阅读 2016-11-08 17:30:54
    Tcp编程下的多线程任务标签(空格分隔): tcp 多线程 TCP通信为毛要引入多线程?基本 TCP 响应服务器一次只能处理一个客户端的请求。当一个客户端向一个已经被其他客户端占用的服务器发送连接请求时,虽然其在连接...
  • TCP编程函数和步骤

    千次阅读 2011-08-18 23:00:01
    TCP编程的服务器端一般步骤是1、 创建一个socket,用函数socket();2、 设置socket属性,用函数setsockopt(); * 可选3、 绑定IP地址、端口等信息到socket上,用函数bind();4、 开启监听,用函数listen();5、...
  • 使用QTcpSocket和QTcpServer进行TCP编程

    千次阅读 2015-12-11 15:13:23
    使用QTcpSocket和QTcpServer进行TCP编程  TCP(传输控制协议)是被大多数英特网协议(包括HTTP和FTP)使用的底层网络协议,主要用于数据传输。它是可靠的,面向流和面向连接的传输协议。它特别适合于连续的数据传输。...
  • Linux下TCP编程,有三个推荐做法,如果没有特殊理由,都这样做。 1、使用SO_REUSEADDR标志,便于TCP Server崩溃后立刻重启在原来的端口上监听 2、程序启动时忽略SIGPIPE信号,防止服务器意外退出。 3、连接使用...
  • 本人是新手开始学习TCP编程: 如下是客户端的代码 ```package Day23.Internet.TCP; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java...
  • VC++ TCP编程实例

    万次阅读 2019-09-24 20:08:46
    AF_INET, // ipv4 internetwork: UDP, TCP, etc SOCK_STREAM, //TCP 0 //protocol ); if(sock == INVALID_SOCKET) { cout,exit"; WSACleanup(); return 0; } SOCKADDR_IN addr_in; memset(&addr_...
  • python之TCP编程

    千次阅读 2019-11-04 17:27:14
    TCP应该分为服务器和客户端,应该先打开服务器再打开客户端 服务器端 主要步骤 买个手机 (创建套接字 socket) 插入手机卡 (为套接字绑定端口和ip bind) 将手机设置为正常的响铃状态 (让默认的套接字由主动到被动 ...
  • 认识Socket TCP编程 二、实验内容 (1)命令行界面要可以带多个参数(出程序名之外至少有2个参数,一个是选项,另一个是选项作用的对象。参看ping,netstat等命令) (2)如何实现多个用户连接同一个服务器 (3)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 49,750
精华内容 19,900
关键字:

tcp编程