しょっちゅう忘れることを書いておく。
![]() |
66 |
1121 views
C言語のサンプル
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#define MAX_CHILD 20
typedef void (*RECV_CALLBACK)(char *);
int serverSocket(int portno) {
int soc, opt;
int ret = 0;
struct servent *se;
struct sockaddr_in my;
memset((char *)&my, 0, sizeof(my));
my.sin_family = AF_INET;
my.sin_addr.s_addr = htonl(INADDR_ANY);
my.sin_port = htons(portno);
/* ソケット作成 */
soc = socket(AF_INET, SOCK_STREAM, 0);
if(soc < 0) {
perror("socket");
return -1;
}
/* オプション設定 */
ret = setsockopt(soc, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
if(ret != 0) {
perror("setsockopt");
close(soc);
return -1;
}
/* バインド */
ret = bind(soc, (struct sockaddr *)&my, sizeof(my));
if(ret == -1) {
perror("bind");
close(soc);
return -1;
}
/* バックログ */
ret = listen(soc, SOMAXCONN);
if(ret == -1){
perror("listen");
close(soc);
return -1;
}
return soc;
}
int RecvSendOne(int acc, int child_no, RECV_CALLBACK callBack) {
char buf[512], *ptr;
int len;
if((len = recv(acc, buf, sizeof(buf), 0)) < 0) {
perror("recv");
return -1;
}
if(len==0) {
fprintf(stderr, "[child[%d] recv: EOF\n", child_no);
return 0;
}
/* 文字列化・表示 */
buf[len] = '\0';
/* コールバックを呼び出す */
callBack(buf);
if((ptr=strpbrk(buf, "\r\n")) != NULL) {
*ptr = '\0';
}
fprintf(stderr, "[child%d]%s\n", child_no, buf);
strcat(buf, ":OK\r\n");
len = strlen(buf);
if((len = send(acc, buf, len, 0)) < 0) {
perror("send");
return -1;
}
return 1;
}
int acceptLoop(int soc, RECV_CALLBACK callBack) {
int acc ,len;
struct sockaddr_in from;
int child[MAX_CHILD];
int child_no;
fd_set mask;
int width;
struct timeval timeout;
int i, count, pos, ret;
for(i = 0; i < MAX_CHILD; i++) {
child[i] = -1;
}
child_no = 0;
while(1) {
FD_ZERO(&mask);
FD_SET(soc, &mask);
width = soc + 1;
count = 0;
for(i = 0; i < child_no;i++) {
if(child[i] != -1) {
FD_SET(child[i], &mask);
if(child[i] + 1 > width) {
width = child[i] + 1;
count++;
}
}
}
timeout.tv_sec = 10;
timeout.tv_usec = 0;
switch(select(width, (fd_set *)&mask, NULL, NULL, &timeout)) {
case -1:
perror("select");
return -1;
case 0:
/* タイムアウト */
break;
default:
if(FD_ISSET(soc, &mask)) {
len = sizeof(from);
/* 接続受付 */
acc = accept(soc, (struct sockaddr *)&from, &len);
if(acc < 0) {
if(errno != EINTR) {
perror("accept");
}
}
else {
fprintf(stderr, "accept:%s:%d\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
pos = -1;
for(i=0; i < child_no;i++) {
if(child[i] == -1) {
pos = i;
break;
}
}
if(pos == -1) {
/* 空きがない */
if(child_no+1>=MAX_CHILD){
fprintf(stderr, "child is full: cannot accept\n");
close(acc);
}
else {
child_no++;
pos = child_no - 1;
}
}
if(pos != -1){
child[pos] = acc;
}
}
}
/* アクセプトしたソケットがレディ */
for(i = 0; i < child_no;i++) {
if(child[i] != -1) {
if(FD_ISSET(child[i], &mask)) {
ret = RecvSendOne(child[i], i, callBack);
if(ret <= 0) {
close(child[i]);
child[i] = -1;
}
}
}
}
}
}
return 0;
}
void mainLoop(int port, RECV_CALLBACK callBack) {
int soc;
soc = serverSocket(port);
if(soc == -1) {
fprintf(stderr, "serverSocker (%d): error\n", port);
}
fprintf(stderr,"ready for accept\n");
acceptLoop(soc, callBack);
close(soc);
}
gcc -shared -fPIC -o server.so main.c
# coding:UTF-8
import ctypes
def recv_callback(msg):
print(msg.decode("utf-8"))
if __name__ == '__main__':
libsv = ctypes.CDLL("./server.so")
cfun = ctypes.CFUNCTYPE(None, ctypes.c_char_p)
libsv.mainLoop.restype = None
libsv.mainLoop.argtypes = (ctypes.c_int32, cfun)
libsv.mainLoop(22222, cfun(recv_callback))
Page 20 of 69.
すぺぺぺ
本サイトの作成者。
プログラムは趣味と勉強を兼ねて、のんびり本サイトを作っています。
フレームワークはdjango。
ChatGPTで自動プログラム作成に取り組み中。
https://www.osumoi-stdio.com/novel/