网络编程.网络服务器

  • 准备连接

    1. 客户端建立一个TCP连接分为2步,包括建立socket对象以及调用connect建立一个和服务器的连接,而对于服务器则需要建立socket对象,设置socket选项(可选的),绑定到一个端口(同样,也可以是一个指定的网卡),侦听连接

  • 建立socket对象

cur_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

  • 设置和得到socket选项

cur_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
cur_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)

        1. socket.SO_REUSEADDR标志位为True时,表示当socket关闭后,本地端用于该socket的端口号立刻就可以被重用,默认情况下端口会经过一段时间才会被释放

        2. socket.SO_KEEPALIVE标识位为True时,可以使TCP通信的信息包保持连续性,这些信息包可以在没有信息传输时,使通信的双方确定连接是保持的

  • 绑定socket

cur_socket.bind((bind_host, bind_port))

        1. host为空字符串时表示可以绑定到所有的接口和地址

  • 侦听连接

client_sock, client_addr = cur_socket.accept()

  • 接受连接

    1. 大多数服务器都设置成运行不确定长时间和同时服务于多个连接,常使服务器连续运行的办法是设计一个无限循环

    2. 无限循环会耗净CPU资源,然后这里循环不同,当调用accept时,它只在有一个客户端连接后才返回,此时其实是被阻塞的

  • 处理错误

    1. 服务端一般出现错误并不会关闭服务器,停止响应请求,常常会打印错误并且略过错误

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose: 
#
"""
import sys
import socket
import threading


# 接受连接的线程
def accept_thread(cur_socket):
    """Generate accept thread.

    Args:
        cur_socket: socket with bind (host, port)
    Returns:
        bool
    """

    server_info = cur_socket.getsockname()
    client_sock, client_addr = cur_socket.accept()
    print 'notice: client %s -> server %s' % (repr(client_addr),
                                              repr(server_info))
    while True:
        try:
            cur_buffer = client_sock.recv(2048)
        except (KeyboardInterrupt, SystemExit):
            cur_socket.close()
            return False
        if not cur_buffer.strip():
            cur_socket.close()
            return False
        client_sock.sendall('Recived: %s' % (cur_buffer.upper()))

# 主函数
def main():
    """Main function.
    """
    # 接受连接的线程列表
    accept_thread_list = []

    # 主机设置为空字符串,程序可以接受来自任意地方的连接
    bind_host = ''
    bind_port = 8888
    # 建立SOCKET
    try:
        cur_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    except socket.error, e:
        sys.exit('errors: creating socket with error %s' % (e))
    # SOCKET设置为可复用
    cur_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        bind_port = int(bind_port)
    except ValueError, e:
        try:
            bind_port = socket.getservbyname(bind_port, 'TCP')
        except socket.error, e:
            sys.exit('errors: resolver port with error %s' % (e))
    try:
        cur_socket.bind((bind_host, bind_port))
    except socket.error, e:
        sys.exit('errors: bind with error %s.' % (e))

    # 开始等待来自客户端连接,默认最多只有1个等待处理的连接
    cur_socket.listen(1)

    # 新建10个等待连接
    for _ in xrange(10):
        accept_thread_list.append(threading.Thread(target=accept_thread,
                                                   args=(cur_socket,)))
    # 并行运行接受连接
    for cur_thread in accept_thread_list:
        cur_thread.start()

if __name__ == '__main__':
    main()

  • 使用UDP

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import sys
import socket
import threading


# 主函数
def main():
    """Main function.
    """
    bind_host = ''
    bind_port = 8888

    try:
        cur_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    except socket.error, e:
        sys.exit('errors: creating socket with error %s' % (e))
    cur_socket.bind((bind_host, bind_port))

    server_addr = cur_socket.getsockname()
    # 没有连接概念,客户端每个连接用不同的自动变化端口
    while True:
        client_msg, client_addr = cur_socket.recvfrom(2048)
        print 'notice: client %s -> server %s' % (repr(client_addr),
                                                  repr(server_addr))
        cur_socket.sendto('Recived: %s' % (client_msg.upper()), client_addr)

if __name__ == '__main__':
    main()


转载于:https://my.oschina.net/pydevops/blog/653756

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值