C和PYTHON的SOCKET通信
作者:糖果
[问题] C和python的Socket通信
Socket是linux提供的基础服务,用于实现计算机间的tcp/ip协议通信。python是强大的高级解释行语言,功能抽象程度高,语法简洁功能强大。网络上有很多socket入门例子程序,都是用C语言写的,传统的CS服务器客户端演示程序。
本文提供的同样是最简单的CS结构通信程序,区别是,Server用Python编写,Client用C语言编写。
基础的Socket API 使用是模式化的,没有算法过程,只有配置过程。而pyhon被誉为是可以运行的伪语言,可以更好的说明Socket API的模式化使用步骤。
[解决案]
首先列出Server端程序的Python代码,除了import和print,几乎其中的每一句都是socket API使用步骤中,不可或缺的部分。
C语言使用Socket的套路几乎和python的一样,区别是,C语言本身还要考虑buf空间的申请和释放,判断socket各个步骤成功异常。还要准备hostent结构体和sockaddr结构体,进行更详细定义过程。
import socket
#取得一个socket对象句柄
s = socket.socket()
#取得主机名
host = socket.gethostname()
#定义端口号
port = 1236
#将socket对象句柄,与指定的IP和Port号绑定。
s.bind((host, port))
#服务其开始监听数据
s.listen(5)
#大循环,开始堵塞式的数据读取
while True:
#接受外部链接请求“c”其他客户机与本机链接产生的,新的通信socket句柄,“addr”表示client记得IP地址。
c, addr = s.accept()
#接受1024大的数据
data = c.recv(1024)
print data
print 'Got connection from:', addr, data
#相应链接,把一条英文信息返回给client
c.send('Thank you for connecting:')
#关闭socket链接
c.close()
运行服务器端程序:
python server.py
“坑”提示:代码“c, addr = s.accept()”中,c和addr之间的符号是", "逗号,输入时请注意!
client.c
下面是一段c语言的客户端程序。
一般来说,需要对“hostent”和“sockaddr_in”进行解释,还有对socket, recv, connect,send等API接口参数含义的介绍。就不介绍了,直接在系统里man一下API吧,或是发挥一下自己想象力,然后代码实践,再看文档求证一下吧!因为API不用背,需要动态的理解。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define PORT 1236
#define BUFFER_SIZE 1024
int main(int argc, char** argv)
{
int sock_fd, recvbytes;
char buf[BUFFER_SIZE];
struct hostent *host;
struct sockaddr_in serv_addr;
if (argc < 2) {
fprintf(stderr, "Please enter the server's hostname!\n");
exit(1);
}
if ((host=gethostbyname(argv[1]))== NULL) {
herror("get host b name error!");
}
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Create socket error!");
exit(1);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr = *((struct in_addr*)host->h_addr);
printf("hostname:%s", host->h_addr);
bzero(&(serv_addr.sin_zero), 8);
if (connect(sock_fd, (struct sockaddr* )&serv_addr, sizeof(struct sockaddr)) == -1) {
perror("connect error");
}
if (send(sock_fd, "spring", 8,0) == -1) {
perror("send error!");
}
if ((recvbytes = recv(sock_fd, buf, BUFFER_SIZE, 0)) == -1) {
perror("recv error!");
exit(1);
}
buf[recvbytes] = '\0';
printf("Received:%s", buf);
close(sock_fd);
return 0;
}
编译客户端程序:
[code]gcc -o client client.c[/code]
运行客户端程序:
[code]./client 127.0.0.1[/code]
“坑”提示:C语言程序中的
“if ((recvbytes = recv(sock_fd, buf, BUFFER_SIZE, 0)) == -1) ”这句,不要写成:“if (recvbytes = recv(sock_fd, buf, BUFFER_SIZE, 0) == -1)”
以上的C语言client程序,几乎等同于如下python的client代码。
结合上面的python服务器端的程序注释,下面的client端程序几乎不需要解释。
import socket
s = socket.socket()
host = socket.gethostname()
port = 1236
s.connect((host, port))
s.send(bytes("python"))
print s.recv(1024)
s.close()
[尾声]
socket的API使用相对很简单,于Linux下的打开关闭读写文件类似。而socket API的使用,是建立在对TCP/IP基本概念了解的基础上,至少要了解主机和端口号的概念。项目中几乎不会用这么简单的代码,下一篇介绍select基础,基础原理哥附身。
谨以此文,献给大姐!献给想不起API的青春,再见青春,再见的永远的故乡!峰哥护体。
[赠送内容]
下面是python之间进行UDP通信:
import socket
address = ('127.0.0.1', 1812)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(address)
while True:
data, addr = s.recvfrom(2048)
if not data:
print "client has exist"
break
print "received:", data, "from", addr
s.close()
import socket
address = ('127.0.0.1', 1812)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
msg = raw_input()
if not msg:
break
s.sendto(msg, address)
s.close()
下面是python之间进行TCP通信:
def tcpServer():
srvsock = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
srvsock.bind(('', 1812))
srvsock.listen(5)
while True:
clisock, (remoteHost, remotePort) = srvsock.accept()
print "[%s:%s] connected" % (remoteHost, remotePort)
#do something on the clisock
clisock.close()
if __name__ == "__main__":
tcpServer()
def tcpClient():
clisock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clisock.connect(('localhost', 1812))
#I/O on this clisock
#clisock.send("")
#dat = clisock.recv(len)
print dat
if __name__ == "__main__":
tcpClient()
注释:个人劳动成果,转载使用请注明本文作者及出处链接,谢谢合作!