server program

本文介绍了一次Java程序与C语言程序通过Socket实现通信的实验。C语言端作为服务器,Java端作为客户端。详细展示了代码实现过程及通信结果。
今天上午实验了java程序与c语言程序通过socket进行通信。由于没学过java,因此只是编写了C语言端的代码,java端的代码是从网上别的文章中找的,经过少量修改后与C语言端程序通信成功。

本例中C语言端作为服务器,java端作为客户端

代码如下:

/****************** server program *****************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
#include <pthread.h>
#include <arpa/inet.h>

int sockfd,newfd;
void *read_socket();

int main()
{
    int ret;
    pthread_t read_tid,write_tid;
    struct sockaddr_in server_addr;
    server_addr.sin_family=AF_INET;/*设置域为IPV4*/
    server_addr.sin_addr.s_addr=INADDR_ANY;/*绑定到 INADDR_ANY 地址*/
    server_addr.sin_port=htons(5678);/*通信端口号为5678,注意这里必须要用htons函数处理一下,不能直接写5678,否则可能会连不上*/
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if (sockfd<0)
    {
        printf("调用socket函数建立socket描述符出错!/n");
         exit(1);
    }
    printf("调用socket函数建立socket描述符成功!/n");
    ret=bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(server_addr));
    perror("server");
    if (ret<0)
    {
        printf("调用bind函数绑定套接字与地址出错!/n");
         exit(2);
    }
    printf("调用bind函数绑定套接字与地址成功!/n");
    ret=listen(sockfd,4);
    if (ret<0)
    {
        printf("调用listen函数出错,无法宣告服务器已经可以接受连接!/n");
         exit(3);
    }
    printf("调用listen函数成功,宣告服务器已经可以接受连接请求!/n");
    newfd=accept(sockfd,NULL,NULL);/*newfd连接到调用connect的客户端*/
    if (newfd<0)
    {
        printf("调用accept函数出错,无法接受连接请求,建立连接失败!/n");
         exit(4);
    }
    printf("调用accept函数成功,服务器与客户端建立连接成功!/n");
   
    /** 服务器端建立一个线程,负责从socket读取数据,当然此处并不一定非要建立一个新线程,直接在原线程中写也可以 **/
    pthread_create(&read_tid,NULL,read_socket,NULL);

   
    /********************* 令原线程睡眠 ************************/
    while(1)
    {
        sleep(10000);
    }
}

/****************** 从socket读取数据 ********************/
void *read_socket()
{
    int recv_num,recv_num_total=0;
    char recv_buf[50];
    while (1)
    {
        memset(recv_buf,0,sizeof(recv_buf));/*清空一下recv_buf缓存区*/
        recv_num=recv(newfd,recv_buf,26,0);
        if (recv_num<0)
            printf("服务器端:调用recv接收失败!/n");
        else if(recv_num>0)
        {
            recv_num_total+=recv_num;
            printf("服务器端:调用recv接收成功!本次接收到%d个字节,内容为:/"%s/"。共收到%d个字节的数据。/n",recv_num,recv_buf,recv_num_total);
            sync();
        }
        else/*收到数据为0,表明服务器与客户端的连接已经中断*/
        {
            printf("服务器端:与客户端的连接已中断,当前共收到%d个字节的数据。服务器将再次等待客户端的连接。/n",recv_num_total);
            newfd=accept(sockfd,NULL,NULL);/*当客户端退出后,再次开始接收客户端的连接*/
        }
        sleep(1);
    }
}



/****************** Client program *****************/
import java.net.*;
import java.io.*;

public class Client {
static Socket server;

public static void main(String[] args) throws Exception {
   server = new Socket(InetAddress.getLocalHost(), 5678);
   BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
   PrintWriter out = new PrintWriter(server.getOutputStream());
   BufferedReader wt = new BufferedReader(new InputStreamReader(System.in));

   while (true) {
    String str = wt.readLine();
    out.println(str);
    out.flush();
    if (str.equals("end")) {
     break;
    }
   }
   server.close();
}
}


把服务器端程序存为server.c,客户端程序存为Client.java

编译:
gcc -o server -lpthread server.c
javac Client.java

在两个终端下分别运行服务端和客户端:
./server
java Client

///////////////////////// 客户端运行结果 ////////////////////////////////
hello,this is a socket test!(自己输入一些文字)
good
///////////////////////// 服务端运行结果 ////////////////////////////////
调用socket函数建立socket描述符成功!
server: Success
调用bind函数绑定套接字与地址成功!
调用listen函数成功,宣告服务器已经可以接受连接请求!
调用accept函数成功,服务器与客户端建立连接成功!
服务器端:调用recv接收成功!本次接收到26个字节,内容为:"hello,this is a socket tes"。共收到26个字节的数据。
服务器端:调用recv接收成功!本次接收到3个字节,内容为:"t!
"。共收到29个字节的数据。

服务器端:调用recv接收成功!本次接收到5个字节,内容为:"good
"。共收到34个字节的数据。

=================================

可见通信是成功的,其中客户端发送的第一条消息超过了服务端程序中规定每次读取的字节数(26个字节,在这一句里recv_num=recv(newfd,recv_buf,26,0);设定的),服务端分两次接收了该消息。

另外,客户端输入的换行符也被接收了进来,因此可以看到蓝色字体的这一条返回结果中,t!后面有一个换行,同时显示本次接收到了3个字符。

 

<think>我们正在编写一个BitBake配方(recipe)来编译和安装一个用C语言编写的简单服务器程序。根据用户的问题,我们需要创建一个.bb文件,其中包含获取源代码、编译和安装的步骤。 步骤分解: 1. 创建recipe文件:通常命名为<程序名>_<版本>.bb,例如`simple-server_1.0.bb`。 2. 定义基本元数据:包括摘要(SUMMARY)、描述(DESCRIPTION)、许可证(LICENSE)等。 3. 指定源代码位置(SRC_URI):如果源代码在本地,可以使用`file://`;如果在远程仓库,可以使用git、http等。 4. 设置工作目录(S):源代码解压后的目录。 5. 编写编译任务(do_compile):使用交叉编译器编译C程序。 6. 编写安装任务(do_install):将生成的可执行文件安装到目标目录(通常是${bindir},即/usr/bin)。 假设我们有一个简单的服务器程序,由单个C文件(server.c)组成。我们可以这样编写recipe: ```bitbake SUMMARY = "Simple server program" DESCRIPTION = "A simple server written in C" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" # 假设我们将server.c放在与recipe相同目录下的files子目录中 SRC_URI = "file://server.c" # 设置工作目录为${WORKDIR},因为只有一个文件,解压后就在WORKDIR S = "${WORKDIR}" # 编译任务:使用CC(交叉编译器)编译server.c do_compile() { ${CC} ${CFLAGS} ${LDFLAGS} -o server server.c } # 安装任务:将可执行文件安装到目标系统的/usr/bin目录 do_install() { install -d ${D}${bindir} install -m 0755 server ${D}${bindir} } ``` 注意: - 如果程序有多个源文件,可以将它们都放在files目录下,然后在SRC_URI中列出,或者使用通配符(但要注意BitBake的通配符使用规则)。 - 如果程序需要额外的编译标志(如链接库),可以在do_compile中添加,例如:`${CC} ${CFLAGS} ${LDFLAGS} -o server server.c -lpthread`。 - 许可证文件检查(LIC_FILES_CHKSUM)是必须的,这里我们使用了Yocto中自带的MIT许可证文件。 将上述recipe保存为`simple-server_1.0.bb`,并放在一个自定义的layer中(例如,在`meta-custom/recipes-example/simple-server/`目录下)。 然后,在构建环境中,可以通过以下命令构建: ```bash bitbake simple-server ``` 构建完成后,可执行文件`server`将被安装到目标镜像的`/usr/bin`目录中。 另外,根据引用[1]中的内容,如果需要调试,可以使用`bitbake -e`命令来查看各种变量,例如: ```bash bitbake -e simple-server | grep ^WORKDIR= bitbake -e simple-server | grep ^S= ``` 这有助于定位构建过程中的目录。 如果用户有多个文件,或者需要从git仓库获取源代码,可以修改SRC_URI,例如: ```bitbake SRC_URI = "git://github.com/username/repo.git;protocol=https;branch=main" SRCREV = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` 然后,在do_compile中进入源代码目录(通过${S}指定)进行编译。 注意:在git仓库的情况下,通常需要设置SRCREV为具体的commit id。 以上就是一个简单的服务器程序的BitBake配方编写方法。</think>### 编写 Yocto BitBake 配方编译 C 语言服务器程序 以下是完整的 BitBake 配方示例,用于编译和安装 C 语言编写的简单服务器程序: ```bitbake # simple-server_1.0.bb SUMMARY = "Simple TCP server application" DESCRIPTION = "A lightweight TCP server for embedded systems" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" # 1. 指定源代码位置 SRC_URI = " \ file://server.c \ file://server.h \ file://Makefile \ " # 2. 设置工作目录 S = "${WORKDIR}" # 3. 配置编译任务 do_compile() { # 使用 Makefile 编译 oe_runmake } # 4. 安装可执行文件 do_install() { # 创建目标目录 install -d ${D}${bindir} # 安装服务器程序 install -m 0755 server ${D}${bindir}/simple-server # 安装配置文件(可选) install -d ${D}${sysconfdir}/simple-server install -m 0644 server.conf ${D}${sysconfdir}/simple-server/ } ``` #### 关键组成部分说明: 1. **源代码管理**: - 将服务器程序源码 (`server.c`, `server.h`) 和 `Makefile` 放在配方同级目录的 `files/` 子目录中 - BitBake 会自动将这些文件复制到构建工作区 [^1] 2. **编译配置**: ```makefile # Makefile 示例 CC = ${CC} CFLAGS = ${CFLAGS} LDFLAGS = ${LDFLAGS} all: server server: server.o $(CC) $(LDFLAGS) -o $@ $^ server.o: server.c server.h $(CC) $(CFLAGS) -c $< -o $@ clean: rm -f server *.o ``` 3. **安装过程**: - `${bindir}` 通常对应目标系统的 `/usr/bin` - `${sysconfdir}` 对应 `/etc` - 使用 `install` 命令确保正确的权限设置 #### 构建和调试: 1. **构建命令**: ```bash source oe-init-build-env # 初始化构建环境[^3] bitbake simple-server ``` 2. **定位构建目录**: ```bash # 查找工作目录 bitbake -e simple-server | grep ^WORKDIR= # 查找编译输出 bitbake -e simple-server | grep ^B= ``` 3. **单独执行任务**: ```bash bitbake -c compile simple-server # 仅编译 bitbake -c install simple-server # 仅安装 ``` #### 验证安装: 构建完成后,在目标系统的 `/usr/bin` 目录下应存在 `simple-server` 可执行文件,在 `/etc/simple-server` 目录下应有配置文件。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值