我的第一个socket程序 “时间服务器”

这是我的一个python写的socket程序

主要是改造python参考手册的 时间服务器,增加“线程”和“同步队列”,代码如下:

# -*- coding: utf-8 -*-



#############################################

## timeSvr.py

#############################################

u"""

一个时间服务器,

分别使用线程来处理【接收连接请求】和【发送服务器时间】

请求时间的客户socket放在【同步队列】中

"""



import socket

import time

import struct

import select

import threading

import Queue



PORT = 3000

CON_QUEUE_MAX_SIZE = 5



class CTimeServer:

    

    u"""时间服务器"""

    

    def __init__(self):

        

        try:

            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

            

            self.sock.bind(("", PORT))

            

            self.sock.listen(CON_QUEUE_MAX_SIZE)

            

            print "TimeServer Start on [%s : %d]"%(socket.gethostbyname(socket.gethostname()), PORT)

              

        except socket.error, e:

            print e

        

        #存放尚为处理(发送时间)的cliSock

        cliSockQueue = Queue.Queue(maxsize = 10)

        

        #“接收连接请求”线程   

        self.acceptThread = AcceptConnThread(self.sock, cliSockQueue)

        

        #“发送服务器时间”线程

        self.sendThread = SendThread(self.sock, cliSockQueue)

    

    def Run(self):



        #运行线程

        self.acceptThread.start()

        self.sendThread.start()

        

        self.acceptThread.join()

        self.sendThread.join()
        self.sock.close()

 

class AcceptConnThread(threading.Thread):

    

    u"""“接收连接请求”线程类"""

    

    def __init__(self, svrSock, cliSockQueue):

        

        threading.Thread.__init__(self)

        self.svrSock = svrSock

        self.cliSockQueue = cliSockQueue

        

    def run(self):

        

        while True:

            self.AcceptConn()

    

    def AcceptConn(self):

        

        cliSock, (host, port) = self.svrSock.accept()

        self.cliSockQueue.put(cliSock)

        

        print "Query Time from [%s : %d]"%(host, port)



class SendThread(threading.Thread):

    

    u"""“发送服务器时间”线程类"""

    

    def __init__(self, svrSock, cliSockQueue):

         

        threading.Thread.__init__(self)

        self.svrSock = svrSock

        self.cliSockQueue = cliSockQueue

        

    def run(self):

        

        while True:

            

            cliSock = self.GetNextQueryCliSock()

            t = int(time.time())

            t = struct.pack("!I", t)



            cliSock.send(t)    

            

    def GetNextQueryCliSock(self):

        

        return self.cliSockQueue.get()      

    

if __name__ == "__main__":

    

    CTimeServer().Run()
 
# -*- coding: utf-8 -*-







#############################################



## timeCli.py



#############################################







import socket



import time



import struct







PORT = 37







try:



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



    



    try:



        sock.connect(("127.0.0.1", PORT))



        



        t = sock.recv(4)



        t = struct.unpack("!I", t)[0]



        localT = int(time.time())



        print localT - t



        



        t = time.ctime(t)



        print t



        



    finally:



        sock.close()



    



except socket.error, e:



    print e
好的,我可以提供一些关于使用C语言在Windows系统下实现Socket编程的基本步骤。但需要注意的是,Socket编程需要涉及到网络通信知识和操作系统相关的网络编程API,需要有一定的编程基础和理解。 首先,我们需要了解一下Socket编程的基本概念。Socket是一种通信机制,它提供了一种标准的接口,使得应用程序可以通过网络进行通信。Socket通信需要两个端点,一个是服务器端,一个是客户端。服务器端需要创建一个Socket并绑定到一个IP地址和端口号上,等待客户端的连接。客户端需要创建一个Socket并连接到服务器端的IP地址和端口号上。一旦连接建立,两端可以通过Socket进行数据的传输。 下面是一些基本的步骤: 1. 引入头文件 ```c #include <winsock2.h> ``` 需要使用`winsock2.h`头文件中的API来实现Socket编程。 2. 初始化Winsock库 ```c WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %d\n", iResult); return 1; } ``` 在开始使用Winsock库中的Socket API之前,需要调用`WSAStartup`函数进行初始化。参数`MAKEWORD(2,2)`指定了使用的Winsock版本,返回值为0表示初始化成功,非0表示失败。 3. 创建Socket ```c SOCKET ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ConnectSocket == INVALID_SOCKET) { printf("socket failed: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } ``` 使用`socket`函数创建一个Socket第一个参数指定了使用的地址族,这里使用IPv4地址族,对应的常量为`AF_INET`;第二个参数指定了Socket的类型,这里使用流式Socket,对应的常量为`SOCK_STREAM`;第三个参数指定了使用的协议,这里使用TCP协议,对应的常量为`IPPROTO_TCP`。返回值为Socket的句柄,如果创建失败则返回`INVALID_SOCKET`。 4. 连接服务器 ```c struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); serverAddr.sin_port = htons(8080); int iResult = connect(ConnectSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)); if (iResult == SOCKET_ERROR) { printf("connect failed: %d\n", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } ``` 创建Socket之后,需要使用`connect`函数连接服务器第一个参数为Socket的句柄,第二个参数为指向服务器地址结构体的指针,第三个参数为地址结构体的大小。这里使用了一个简单的服务器地址结构体`sockaddr_in`,其中`sin_family`指定了地址族,`sin_addr.s_addr`指定了IP地址,`sin_port`指定了端口号。注意IP地址需要使用`inet_addr`函数进行转换,端口号需要使用`htons`函数进行字节序转换。返回值为0表示连接成功,非0表示失败。 5. 发送和接收数据 ```c char sendbuf[1024]; char recvbuf[1024]; int iResult = send(ConnectSocket, sendbuf, strlen(sendbuf), 0); if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } iResult = recv(ConnectSocket, recvbuf, sizeof(recvbuf), 0); if (iResult > 0) { printf("Received: %s\n", recvbuf); } else if (iResult == 0) { printf("Connection closed\n"); } else { printf("recv failed: %d\n", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } ``` 连接建立之后,客户端可以通过`send`函数向服务器发送数据,通过`recv`函数接收服务器发送的数据。`sendbuf`和`recvbuf`分别是发送和接收数据的缓冲区。`send`函数的第一个参数为Socket的句柄,第二个参数为发送数据的缓冲区,第三个参数为发送数据的长度,第四个参数为标志位,这里设为0。`recv`函数的第一个参数为Socket的句柄,第二个参数为接收数据的缓冲区,第三个参数为接收数据的长度,第四个参数为标志位,这里设为0。返回值为接收到的字节数,如果为0表示连接已关闭,小于0表示接收失败。 6. 关闭Socket和Winsock库 ```c closesocket(ConnectSocket); WSACleanup(); ``` 在通信结束后,需要使用`closesocket`函数关闭Socket,使用`WSACleanup`函数关闭Winsock库的使用。 以上就是一个简单的Socket客户端程序的基本步骤。需要注意的是,Socket编程需要处理各种异常情况,如连接失败、发送和接收数据失败等,需要进行错误处理和异常处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值